# Django **Repository Path**: gitliu-yu/django ## Basic Information - **Project Name**: Django - **Description**: Django - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-09-04 - **Last Updated**: 2023-09-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Django是一个使用Python编写的开源Web框架。它可以帮助我们快速开发数据库驱动的Web应用。 ## 文件框架图展示一下Django项目各个文件之间的层级关系: myproject ├── manage.py ├── myproject │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ ├── asgi.py │ └── wsgi.py ├── apps │ ├── __init__.py │ ├── app1 │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── models.py │ │ ├── tests.py │ │ ├── views.py │ │ └── ... │ └── app2 │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── tests.py │ ├── views.py │ └── ... ├── templates ├── static └── media ### Django框架的典型文件目录结构和每个文件作用如下: - manage.py: 该文件是项目管理的主程序,可以通过它来运行项目程序、管理app、数据库迁移等操作。 - **init**.py: 标识该目录是一个Python包。 - settings.py: 项目的配置文件,定义了项目的一些全局设置,比如INSTALLED_APPS、DATABASES、语言时间等配置。 - urls.py: 项目的URL声明,由一系列的url模式组成。 - wsgi.py: 项目与WSGI兼容的Web服务器入口。 - asgi.py: 项目与ASGI兼容的Web服务器入口。 - apps/: 存放项目所用的应用程序目录。 - templates/: 存放项目所用的模板目录。 - static/: 存放静态文件目录,如css、js、图片等。 - media/: 存放上传的媒体文件目录。 - models.py: 应用的数据模型定义文件。 - views.py: 应用的视图函数文件。 - forms.py: 应用的表单定义文件。 - tests.py: 应用的自动化测试用例文件。 - admin.py: 应用在admin后台的配置文件。 所以Django遵循模型(model)-模板(template)-视图(view)的结构,通过这些文件和目录来组织一个项目。 ### 主要说明几点: - manage.py 在项目根目录下,用于管理整个项目。 - myproject/ 表示项目的配置目录。 - apps/ 存放各个应用app。 - templates/ 存放所有应用的模板文件。 - static/ media/ 存放所有应用的静态文件和媒体文件。 每个app下面则有独立的models、views等文件,实现该app的功能。 这样的层级结构能够很好地区分项目和应用,也便于调用和管理。 ## 创建app文件夹 首先删除 */migrations/views.py 文件中的 TEMPLATES 里的 'DIRS': [BASE_DIR / 'templates'] 中的 BASE_DIR / 'templates', 这个是pycharm创建Django时自带的参数,删除后才可正常创建app文件夹。 ![输入图片说明](Django.assets/image-20230806213354655.png) 删除后,在终端执行创建命令: ```shell python manage.py startapp app名字 ``` 也可替换为: ```py 'DIRS': [os.path.join(BASE_DIR, 'templates')] ``` 替换后,可以识别全局的templates文件,并且不影响创建app文件命令 ## 启动Django 在终端执行 ```python python manage.py runserver ``` ![输入图片说明](Django.assets/start-django.png) ## templates文件 F:\PycharmFile\Django20230806\app01\templates F:\PycharmFile\Django20230806\templates 其中app01目录下的是手动创建的;Django20230806下的是创建django项目时自带的,并且它是紫色的文件夹 ### 这两个templates目录的区别在于: - F:\PycharmFile\Django20230806\templates 是项目级的templates目录,在创建Django项目时自动生成。存放全局可用的模板文件。 - F:\PycharmFile\Django20230806\app01\templates 是应用app01独有的templates目录。我们可以在每个app内都创建templates目录,用来存放该app的模板文件。 ### [os.path.join(BASE_DIR, 'templates')]参数作用 - 'DIRS': [os.path.join(BASE_DIR, 'templates')] - os.path.join(BASE_DIR, 'templates') 这一行的作用是指定一个目录路径加入到 TEMPLATES配置中的 DIRS 设置当中。 - BASE_DIR 是项目目录, os.path.join拼接后的路径就是项目根目录下的 templates/ 路径。 - 这行代码使Django 在加载模板文件时,也去该目录下查找。 ### 如果同时存在这两个templates目录,Django会**优先**加载项目根目录下的全局templates目录中的模板文件。 - 只有当项目根目录下没有找到指定的模板时,才会退回到应用本地的(也就是创建的应用中的)templates目录中查找。 - 这实现了模板文件的优先级和继承关系,通常会将一些通用的模板或基模板放在全局目录,而应用相关的模板在各自目录中。 ## Django框架下的引用JavaScript、bootstrap和jQuery文件的,html格式 ```html {% load static %} Demo Page ``` 具体分析: 1. 首先需要加载 {% load static %} 来引用静态文件 2. link标签引入Bootstrap CSS文件 3. script标签引入jQuery和Bootstrap的js文件 4. 可以添加自定义js文件 5. {% static %} 标签会为文件生成正确的静态文件路径 ### 在 Bootstrap 中,ms 和 me 表示 margin 开头的间距utility类,它们的区别是: - ms 表示 margin-start,用于设置元素的左外边距(LTR模式)。 - me 表示 margin-end,用于设置元素的右外边距(LTR模式)。 举例来说: - ms-auto 会将元素左外边距设为auto,从而使其向右对齐。 - me-auto 会将元素右外边距设为auto,使其向左对齐。 在 Flexbox 布局下: - ms-auto 让元素右浮动 - me-auto 让元素左浮动 其中: - start 和 end 表示方向开始和结束 - left 和 right 取决于语言,LTR或者RTL 所以 ms 和 me 是一种智能的写法,可以根据语言环境自动适配。 简单记: - ms 推开左边距 - me 推开右边距 这样可以更灵活地控制组件的对齐方式。 ### 在Django模板语言中,可以使用 `{#% comment %}{% endcomment %}` 来添加注释。 这种格式是Django模板语言中专门用来添加注释的标签。 ``{#%`` 表示注释的开头,``{% endcomment %}`` 表示注释的结束。 在开始和结束标签之间的内容都会被Django解释器忽略,仅作为注释使用。 例如: ```html {# 这是一条注释 #} {# 这是 多行注释 #} ``` 这些内容不会被渲染到最终生成的页面中。 与HTML注释 ```` 不同,模板注释不会保留到HTML源码中,是纯服务器端的注释。 使用模板注释可以注释掉一些调试信息,或注释掉不需要渲染的代码。 总之,在Django模板中使用 ``{#% comment %}{% endcomment %}`` 来添加注释是标准的做法,可以提高代码可读性。 ## 模板语法逻辑 ![输入图片说明](Django.assets/image-20230809000954836.png) ## ORM框架 ![输入图片说明](Django.assets/orm.png) ### Django ORM的工作流程是: 1. 根据模型类自动生成数据库表 2. 提供便捷的数据库查询接口 3. 根据对象操作自动转换为SQL语句 4. 可以方便地转换查询结果为对象 5. 支持数据库迁移和版本控制 Django的ORM框架自带在Django中,开发者主要通过模型Model类定义模型从而操作数据库,可以大大简化数据库操作。Django内置的ORM提供了非常强大的数据库抽象和便捷的使用方式。 ### ORM(Object Relational Mapping)是对象关系映射的英文缩写,中文完整翻译为“对象关系映射”。 ORM是一种程序技术,主要用于实现面向对象编程语言里不同类型系统的数据之间的转换。 主要指将软件对象映射到关系型数据库中的数据表,将对象的属性映射到表的字段上。 ORM的主要作用包括: - 建立对象与关系数据库的数据表之间的映射关系 - 基于面向对象的语法实现对数据库的操作 - 隐藏数据库访问细节,提供更科学的访问方式 - 实现数据模型与数据库schema的解耦 - 更简单的数据库编程接口和数据抽象能力 - 对数据库的基础访问进行封装和优化 所以ORM是一种常用的程序技术,而不是一个特定产品,全称为Object Relational Mapping,提供了将软件对象与关系数据之间实现自动转换的能力。 在许多语言和框架中都有ORM的实现,如Java的Hibernate,Python的Django等。 ## orm-链接mysql配置 创建数据库: ```mysql CREATE DATABASE your_db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; ``` 在setting.py文件中 ```mysql DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'your_db_name', 'USER': 'your_user_name', 'PASSWORD': 'your_password', 'HOST': 'localhost', 'PORT': '3306', } } ``` ## 迁移命令 在models.py文件创建class类后,在终端执行 运行迁移命令,在数据库中创建表 ``` python manage.py makemigrations python manage.py migrate ``` ![输入图片说明](Django.assets/qianyi-1.png) 这将根据models.py中的模型定义在数据库中创建对应表。 重启开发服务器:修改了models.py需要重新启动服务器以生效。 ![输入图片说明](Django.assets/qianyi-2.png) 如果需要删除数据库,将对应的class类注释或删除后再次运行迁移命令即可 ![输入图片说明](Django.assets/qianyi-3.png) 同理,对数据库一些其他操作也是这样进行 ### 已有的数据库可能已经存在数据,再添加列时,执行迁移命令会出现如下情况: ![输入图片说明](Django.assets/image-20230810092110980.png) ``` 1) Provide a one-off default now (will be set on all existing rows with a null value for this column) 2) Quit, and let me add a default in models.py Select an option: ``` #### Django提供了两种解决方案: 1. 为这个新字段提供一个默认值,这将被应用到所有现有的空值行。 2. 退出迁移,去models.py中为这个字段提供一个默认值。 对于选择1,我们需要在命令行提示输入一个默认值,例如'未知'。这将被写入现有所有null的行。 对于选择2,我们需要编辑models.py,为字段提供一个default参数: ```py 字段 = models.CharField(max_length=8, default='未知') ``` 然后重新运行迁移命令。 我推荐选择第二种方案,在models中直接设置默认值'未知',因为代码上更清晰,也避免了输入默认值的步骤。 设置默认值后,Django就能自动将其应用到现有空行,新的行也会使用默认值。这样迁移就可以正常执行了。 所以遇到新增非空字段的情况,一定要记得在models中设置default参数,或在迁移时提供默认值。 ## 模板的继承 ### 定义模板 ```html Title
{% block content %}{% enblock %}
``` ### 继承模板 ```html {% extends '母版名称.html' %} {% block content %}

内容

{% enblock %} ``` ## 模板重复使用 ### 定义模板(统一使用参数:title、form) ```html {% extends 'layout.html' %} {% block content %} {% comment %} 表单 {% endcomment %} Plus Icon {{ title }}
{% csrf_token %} {% for field in form %}
{{ field }} {{ field.errors.0 }}
{% endfor %} {% endblock %} ``` ### 传参title、form ```py def admin_add(request): """ 添加管理用户 """ title = "添加管理用户" if request.method == "GET": form = AdminModelFrom() return render(request, "change.html", {"title":title, "form":form}) ``` ## Cookie和Session ![输入图片说明](image-20230818152101603.png) Cookie 和 Session 都是用于跟踪和保持 web 应用程序用户状态的机制,但两者在实现上有些差异: 1. 存储位置不同 - Cookie 数据保存在客户端(浏览器端),它会在浏览器请求时自动发送给服务器。 - Session 数据存储在服务器端。 2. 安全性不同 - Cookie 存储在客户端,可能被客户端修改,不太安全。 - Session 存储在服务器端,相对更安全。 3. 存储容量不同 - Cookie 数据不能超过 4KB,比较适合存储少量数据。 - Session 没有数据大小限制。 4. 有效期不同 - Cookie可以设置失效时间,默认是当浏览器关闭就失效。 - Session默认在一定没有活动时间后失效(如20分钟),可以设置失效时间。 5. 依赖关系不同 - Cookie可以独立于会话存在,只需要在客户端的首次请求时写入。 - Session 依赖于会话,需在服务器上生成,若会话过期则失效。 总结为: - Cookie适合存储少量的不太敏感的数据。 - Session用于对用户身份的相关敏感信息的跟踪,依赖服务器端会话。 根据数据的类别及安全性要求进行选型。 ### 数据库Session(django_session) ![输入图片说明](Django.assets/image-20230819142043500.png) ## 中间件 中间件是Django框架中的一个类,叫做MiddlewareMixin。它是用来写中间件类的。在Django中,中间件是一个可以处理请求和响应的组件,它可以在请求到达视图函数之前或响应返回客户端之前执行一些操作。而MiddlewareMixin就是用来定义中间件类的。 中间件是Django请求/响应处理的钩子框架。它是一个轻量级的、低级的“插件”系统,用于全局改变Django的输入或输出。每个中间件组件负责做一些特定的功能。例如,Django包含一个中间件组件AuthenticationMiddleware,它使用会话将用户与请求相关联。 ![输入图片说明](Django.assets/image-20230819143927580.png) ### .py文件 ```py from django.utils.deprecation import MiddlewareMixin class M1(MiddlewareMixin): """ 中间件1 """ def process_request(self, request): print("M1进来了") def process_response(self, request, response): print("M1出去了") return response class M2(MiddlewareMixin): """ 中间件2 """ def process_request(self, request): print("M2进来了") def process_response(self, request, response): print("M2出去了") return response ``` setting.py ```py MIDDLEWARE = [ ...... 'app01.middleware.auth.M1', 'app01.middleware.auth.M2', ] ``` ![输入图片说明](Django.assets/image-20230819190231942.png) ### 在中间件的process_request方法 - 如果方法中没有返回值 (返回None) ,继续向后走 - 如果有返回值 HttpResponse、render 、redirect,则不再继续向后执行 ## 注销session ```py def logout(request): """ 注销 """ request.session.clear() return redirect('/login/') ``` ## 图片验证码 ``` import random from PIL import Image, ImageDraw, ImageFont, ImageFilter def check_code(width=120, height=30, char_length=5, font_file = r'F:\PycharmFile\djangoProject1\Monaco.ttf', font_size=28): code = [] img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255)) draw = ImageDraw.Draw(img, mode='RGB') def rndChar(): """ 生成随机字母 :return: """ # return str(random.randint(0, 9)) return chr(random.randint(65, 90)) def rndColor(): """ 生成随机颜色 :return: """ return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255)) # 写文字 font = ImageFont.truetype(font_file, font_size) for i in range(char_length): char = rndChar() code.append(char) h = random.randint(0, 4) draw.text([i * width / char_length, h], char, font=font, fill=rndColor()) # 写干扰点 for i in range(40): draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor()) # 写干扰圆圈 for i in range(40): draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor()) x = random.randint(0, width) y = random.randint(0, height) draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor()) # 画干扰线 for i in range(5): x1 = random.randint(0, width) y1 = random.randint(0, height) x2 = random.randint(0, width) y2 = random.randint(0, height) draw.line((x1, y1, x2, y2), fill=rndColor()) img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) return img, ''.join(code) # if __name__ == '__main__': # img,code_str = check_code() # print(code_str) # # with open('code.png', 'wb') as f: # img.save(f, format='png') ``` ## ajax ### get请求 ```html {% extends "layout.html" %} {% block content %}

任务列表

示例1

{% endblock %} {% block js %} {% endblock %} ``` ### post请求 #### 免除csrf验证 ##### html文件 ``` {% extends "layout.html" %} {% block content %}

任务列表

示例1

{% endblock %} {% block js %} {% endblock %} ``` ##### py文件 ```py from django.shortcuts import render, HttpResponse from django.views.decorators.csrf import csrf_exempt def task_list(request): """ 任务列表 """ return render(request, "task_list.html") @csrf_exempt def task_ajax(request): return HttpResponse("大黑子") ``` ### 关闭绑定事件 原来是通过onclick="clickMe();"绑定 ```html {% extends "layout.html" %} {% block content %}

任务列表

示例1

{% endblock %} {% block js %} {% endblock %} ``` ### ajax请求的返回值 ```py import json from django.shortcuts import render, HttpResponse from django.views.decorators.csrf import csrf_exempt def task_list(request): """ 任务列表 """ return render(request, "task_list.html") @csrf_exempt def task_ajax(request): data_dict = {"status":True, 'data':[6, 66, 666]} return HttpResponse(json.dumps(data_dict)) ``` ### js方式和data方式 ```html {% extends 'layout.html' %} {% block content %}

点击按钮新建订单

{% endblock %} {% block js %} {% endblock %} ``` 这两种打开模态框的方式主要有以下区别: 1. 使用js方式: ```js $('#btnAdd').click(function(){ $('#myModal').modal('show'); }) ``` 这种方式是通过js代码绑定点击事件,在事件回调函数中通过modal('show')打开模态框。这种方式可以灵活控制打开逻辑,比如添加一些其他代码。 2. 使用data属性: ```html