### Django #### Django 特性 1. 优点 1. 重量级框架,框架本身封装了丰富的功能组件 2. 完善的开发文档 3. 开发效率快 2. 缺点 1. 开发不够灵活、自由,不能够完成高度定制化开发 2. 执行速度慢 #### Django 安装 ##### Django 安装 (使用 2.2.1 最稳定) 1. anaconda 虚拟环境操作 1. 创建虚拟环境 : `conda create -n 虚拟环境名 python=3.7` 2. 激活虚拟环境 : `activate 虚拟环境名` 3. 退出虚拟环境 : `deactivate` 4. 查看虚拟环境 : `conda env list` 2. 安装 Django : `pip install django==2.2.1 -i 国内源地址` ##### 创建项目 1. 创建工程 1. 创建一个目录 2. 进入目录打开终端 3. 激活虚拟环境 : `activate DjangoPath` 4. 创建工程 : `django-admin startproject 工程名` 2. Django 项目启动 1. 进入 Django 项目 manage.py 同级目录 2. 激活虚拟环境 3. 启动项目 + `python manage.py runserver` + `python manage.py runserver 9000` : 修改端口 + `python manage.py runserver 0.0.0.0:9000` : 局域网开放并修改端口 + 设置 setting.py 中的 `ALLOWED_HOST =['*']` 3. 目录结构 + 目录名 + 主目录 + `__init__.py` : 主目录初始化文件 + `settings.py` : 项目配置文件 + `urls.py` : 项目的主路由文件 + `wsgi.py` : 项目的部署文件 + `db.sqlit3` : 启动项目后出现 sqlite3 数据库文件 + `manage.py` : 项目的管理文件,负责项目的管理、启动 ##### Django 第一个项目 + 在主目录下创建 `views.py` ```python from django.shortcuts import HttpResponse def hello(request): return HttpResponse('hello word') ``` + 请求流程 1. 请求 /hello/ 2. Django 查看 `setting.py` 中的 ROOT_URLCONF 设置, 找到根 URL 配置 3. Django 比较 URL 配置中各个 URL 模式,找到与 /hello/ 匹配的那个 4. 找到匹配模式就调用对应视图函数 5. 视图函数返回一个 HttpResponse 对象 ##### Django 路由 + 基本格式 ```python from django.contrib import admin from django.urls import path from .views import * urlpatterns = { path('admin/', admin.site.urls), path('hello/', hello) } ``` + 两种格式 1. `path("字符串", 要执行任务的视图)` 2. `re_path("正则表达式", 要执行的任务视图)` + Django 中 路由正则匹配 + `re_path(r'^\w/$', views.zf)` : \w匹配任意一个字母数字下划线 + `re_path(r'^\w+/$', views.zf)` : + 匹配前面表达式以次或多次 + `re_path(r'^\d/$', views.blog)` : 匹配任意数字 + 分组匹配 + 通过分组匹配将 url 路径部分内容,传递到视图函数 + 通过 () 方式,将匹配到的内容传递给视图函数的形参 + 分组命名匹配 + 更直观的分组匹配 + (?P<名称>正则表达式) #### Django 模板 ##### 模板加载 + 在 manage.py 同级下创建 文件夹 templates 存放 HTML 模板 + 在 setting.py 下进行读取模板配置 ```python TEMPLATES = [ { ... 'DIRS' : [os.path.join(BASE_DIR, 'templates')], ... } ] ``` + 建立 HTML 文件 + 在 views.py 中 返回页面 ```python from django.shortcuts import HttpResponse, render_to_response def hello(request): # return HttpResponse('hello word') return render_to_response('hello.html') ``` ##### 模板语法 + 变量 + 语法 : `{{ 变量名 }}` + 变量传参 1. 以 字典形式传参 ```python def index(request): uer_info = {'name': "张三", 'age': 12} hobbies = ['篮球', '足球'] return render(request, 'index.html', { 'user_info': user_info, 'hobbies': hobbies, }) ``` 2. 以 locals() 集体传参 ```python def index(request): uer_info = {'name': "张三", 'age': 12} hobbies = ['篮球', '足球'] return render(request, 'index.html', locals()) ``` + 支持类型为 : 字符串、整型、列表、字典、元组 + 变量为字典可以通过键取值 + 变量为可迭代对象可以使用索引取值 + 标签 + 语法 : **{% %}** + 结构 1. if 结构 ```jinja2 {% if 条件 %} 执行语句 {% elif 条件 %} 执行语句 {% endif %} ``` 2. ifequal 结构 ```jinja2 {% ifequal age 19 %}

成年

{% endifequal %} ``` 3. for 循环结构 + forloop : 记录循环次数, 常与 if 一起使用 4. for ... empty 循环 ```jinja2 {% for i in arr %} {{ i }} {% empty %} 列表内没有 i {% endfor %} ``` 5. autoescape off 关闭自动转义 ```jinja2 {% autoescape on %} {{ url }} {% endautoescape %} {% autoescape off %} {{ url }} {% endautoescape %} ``` + 过滤器 + 语法 : `{{ name|过滤器方法: 传值 }}` 用于对传入视图函数值二次处理 ##### 静态文件处理 1. 方法一 1. 在 manage.py 同级目录下创建 static 文件夹, 用来存放静态 JS、CSS、图片等文件 2. 在 setting.py 内配置 ```python STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ] ``` 3. 在 html 文件内加载静态资源 ```html > **more setting** 内 创建 App #### Django 数据库 ##### ORM 介绍 1. Object Relational Mapping (ORM 对象关系映射) : 将面向对象语言程序中的对象自动持久化到关系数据库中.本质是将数据从一种形式 (对象) 转换到另一种形式 (数据库表格) 2. ORM 转换对应关系 1. Python 中一个类 <----> 数据库中一张表格 2. Python 中一个对象 <----> 数据库表格中一条记录 3. Python 中类的属性 <----> 数据库表格中的字段 3. ORM 优势 + ORM 提供数据库的映射, 不直接编写 SQL 代码, 操作数据库只需要像操作对象一样.提高了开发效率. 4. ORM 劣势 + 一定程度上牺牲程序效率 ##### DjangoOrm 建模 + Django 数据库模型必须在 App 当中的 models 中创建 ##### 数据库配置 1. 配置 MySQL 数据库 1. 设置数据库配置信息 ```python DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'db_name', 'USER': 'user_name', 'PASSWORD': 'user_password', 'HOST': 'HOST_IP', 'PORT': 'mysql_port', # 默认 3306 } } ``` 2. 下载 PyMySQL 模块,在 项目包的 `__init__.py` 下 ```python import pymysql pymysql.install_as_PyMySQLdb() ``` 3. 排错 : Django 2.2.1 与 PyMySQL 不兼容需要修改源码 1. 生成数据库映射时报错 ``` Traceback (most recent call last): File "manage.py", line 21, in main() File "manage.py", line 17, in main execute_from_command_line(sys.argv) File "E:\Anaconda\envs\mydjango\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line utility.execute() File "E:\Anaconda\envs\mydjango\lib\site-packages\django\core\management\__init__.py", line 375, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "E:\Anaconda\envs\mydjango\lib\site-packages\django\core\management\base.py", line 323, in run_from_argv self.execute(*args, **cmd_options) File "E:\Anaconda\envs\mydjango\lib\site-packages\django\core\management\base.py", line 364, in execute output = self.handle(*args, **options) File "E:\Anaconda\envs\mydjango\lib\site-packages\django\core\management\base.py", line 83, in wrapped res = handle_func(*args, **kwargs) File "E:\Anaconda\envs\mydjango\lib\site-packages\django\core\management\commands\makemigrations.py", line 101, in handle loader.check_consistent_history(connection) File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\migrations\loader.py", line 283, in check_consistent_history applied = recorder.applied_migrations() File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\migrations\recorder.py", line 73, in applied_migrations if self.has_table(): File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\migrations\recorder.py", line 56, in has_table return self.Migration._meta.db_table in self.connection.introspection.table_names(self.connection.cursor()) File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\backends\base\base.py", line 256, in cursor return self._cursor() File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\backends\base\base.py", line 233, in _cursor self.ensure_connection() File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\backends\base\base.py", line 217, in ensure_connection self.connect() File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\backends\base\base.py", line 197, in connect self.init_connection_state() File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\backends\mysql\base.py", line 231, in init_connection_state if self.features.is_sql_auto_is_null_enabled: File "E:\Anaconda\envs\mydjango\lib\site-packages\django\utils\functional.py", line 80, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\backends\mysql\features.py", line 82, in is_sql_auto_is_null_enabled cursor.execute('SELECT @@SQL_AUTO_IS_NULL') File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\backends\utils.py", line 103, in execute sql = self.db.ops.last_executed_query(self.cursor, sql, params) File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\backends\mysql\operations.py", line 146, in last_executed_query query = query.decode(errors='replace') AttributeError: 'str' object has no attribute 'decode' ``` 2. 修改源码: `File "E:\Anaconda\envs\mydjango\lib\site-packages\django\db\backends\mysql\operations.py", line 146, in last_executed_queryquery = query.decode(errors='replace')`原为 decode ,python3 无此方法,改为 encode ```python def last_executed_query(self, cursor, sql, params): # With MySQLdb, cursor objects have an (undocumented) "_executed" # attribute where the exact query sent to the database is saved. # See MySQLdb/cursors.py in the source distribution. query = getattr(cursor, '_executed', None) if query is not None: query = query.encode(errors='replace') # 原为 decode ,python3 无此方法,改为 encode return query ``` 3. 继续进行数据库检查、生成映射、同步至数据库 2. 配置 sqlite3 数据库 + 配置 ```python DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } ``` 3. 数据迁移 (添加新的数据库表时) 1. `python manage.py check` : 检测数据库配置是否有错误 2. `python manage.py makemigrations app_name` : 生成数据库映射文件 3. `python manage.py migrate` : 同步数据库 4. Django 模型常用字段 | 字段名称 | 字段描述 | | -------------------------------------- | ------------------------------------------------------------ | | `models.CharField(max_length=32)` | 字符串类型,必须设置 max_length | | `models.IntergerField()` | 整数类型 | | `models.FloatField()` | 小数类型 | | `models.TextField()` | 文本类型 | | `models.EmailField()` | 邮件格式的字符串 | | `models.DateField()` | 日期格式 (年月日) | | `models.DateTimeField()` | 时间格式 (年月日时分秒) | | `models.FileField(upload_to=file_dir)` | 文件类型, 特殊类型,可以保存文件路径同时自动上传文件,必须设置 upload_to 上传到媒体路径下的位置 | | `models.ImageField(upload_to=img_dir)` | 图片类型, 特殊类型 (需要提前配置),可以保存文件路径同时自动上传文件,必须设置 upload_to 上传到媒体路径下的位置 | | `电话类型` | 必须是美国座机格式的电话号 | + 配置 ImageField 保存图片 1. 安装 pillow 模块 : `pip install pillow` 2. `setting.py` 配置媒体文件 ```python MEDIA_URL = "/media/" MEDIA_ROOT = os.path.join(BASE_DIR, 'static') ``` 5. Django 数据库常用的字段参数 | 参数名称 | 参数描述 | | -------------- | ---------------------------- | | `verbose_name` | 别名,在后台可以使用 | | `default` | 默认值 | | `unique` | 不可重复 | | `blank` | 可以为空,常用于字符串 | | `null` | 可以为 null 常用于数字和时间 | | `max_length` | 字符串长度范围 | | `upload_to` | 文件上传地址 | | `Auto_now` | 默认当前时间 | 6. Django ORM 总结 1. Django ORM 默认自带 id 主键 2. Django ORM 默认字段不为空,为了方便,通常可以设置 blank 和 null