Django
Django介绍
介绍Django是Python语言中的一个Web框架,Python语言中主流的web框架有Django、Tornado、Flask等多种
优势:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等功能,是一个全能型框架,拥有自己的Admin数据管理后台,第三方工具齐全,性能折中
缺点:功能太多,数据分表复杂,高性能扩展复杂、重量级
Django安装
pip安装:在cmd命令窗口中,输入:
1 | pip install django |
提示
- 点击页面右下角的language按钮,可以选择zh-hans,显示中文,只有部分页面有中文翻译
- 点击页面右下角的Documentation version,可以选择版本
专业词汇
B/S和C/S
Django是用于开发B/S架构的软件的,软件主要分为B/S架构和C/S架构:
- B/S:全称Browser/Server(浏览器/服务器)
- C/S:全称Client/Server(客户端/服务器)
MVC和MTV
MVC
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
- M:管理应用程序的状态(通常存储到数据库中),并约束改变状态的行为(或者叫做“业务规则”)。
- V:负责把数据格式化后呈现给用户。
- C:接受外部用户的操作,根据操作访问模型获取数据,并调用“视图”显示这些数据。控制器是将“模型”和“视图”隔离,并成为二者之间的联系纽带。
MTV
Django也是一个MVC框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以Django里更关注的是模型、模板(Template)和视图,称为MTV模式:
- M:代表模型,即数据存取层。该层处理与数据相关的所有事务:如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
- T:代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示。
- V:代表视图(View),即业务逻辑层。该层包含存取模型及调取恰当模板的相关逻辑。你可以把它看作模型与模板之间的桥梁。
ORM
ORM就是通过实例对象的语法,完成关系型数据库的操作的技术,是”对象-关系映射”(Object/Relational Mapping)的缩写
ORM:把数据库映射成对象
举例来说,下面是一行SQL语句。
1 | SELECT id, first_name, last_name, phone, |
程序直接运行SQL,操作数据库的写法如下。
1 | res = db.execSql(sql); |
改成ORM的写法如下。
1 | p = Person.get(10); |
比较一下就可以发现,ORM使用对象,封装了数据库操作,因此可以不碰SQL语言。开发者只使用面向对象编程,与数据对象直接交互,不用关心底层数据库
ORM有下面这些优点
- 数据模型都在一个地方定义,更容易更新和维护,也利于重用代码
- ORM有现成的工具,很多功能都可以自动完成,比如数据初始化、事务等等
- 它迫使你使用MVC架构,ORM就是天然的Model,最终使代码更清晰
- 基于ORM的业务代码比较简单,代码量少,语义性好,容易理解
- 不必编写性能不佳的SQL
ORM也有很突出的缺点
- ORM库不是轻量级工具,需要花很多精力学习和设置
- 对于复杂的查询,ORM要么是无法表达,要么是性能不如原生的SQL
- ORM抽象掉了数据库层,开发者无法了解底层的数据库操作,也无法定制一些特殊的SQL
Django项目搭建
创建项目
在命令行中执行代码
1 | django-admin startproject demo |
- django-admin为内部命令
- startproject为参数
- demo项目名
备注
避免使用Python或Django的内部保留字来命名项目。比如说,避免使用像django(会和Django自己产生冲突)或test(会和Python的内置组件产生冲突)这样的名字
项目结构
1 | demo/ #项目的名称 |
启动项目
- 命令行窗口中,进入最外层的demo
- 运行命令
- python manage.py runserver
- 额外参数
- python manage.py runserver 8000
- python manage.py runserver 127.0.0.1:8001
- 查看运行日志
- 检查服务,查看欢迎页面
在浏览器输入:http://127.0.0.1:8000或者http://localhost:8000
第一个Django程序
创建一个子应用
1
python manage.py startapp myapp01
修改settings.py配置
1
2
3
4
5
6
7
8
9INSTALLED_APPS=[
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp01' #子应用必须配置,否则不起作用
]修改urls.py配置
1
2
3
4
5
6from first_app import views
urlpatterns=[
path('admin/',admin.site.urls),
path('test/',views.first_test),
]修改views.py配置
1
2
3
4
5
6
7from django.http import HttpResponse
#Createyourviewshere.
deffirst_test(request):
print('第一个Django项目views')
return HttpResponse('Django项目第一次请求成功')
Django配置文件-初识
介绍
Django项目创建后,在主应用中,会有一个settings.py文件,这个就是该项目的配置文件
- settings文件包含Django安装的所有配置
- settings文件是一个包含模块级变量的python模块,所以该模块本身必须符合python规则,并且可以使用python的语法
- settings中的所有配置项的key必须全部大写
- settings中每一个配置项都有默认值,默认配置内容在django/conf/global_settings.py中可以查看到,项目中不需要导入该模块,django框架会自动获取
- settings中可以添加自定义的配置项
配置文件的使用
- manage.py启动
1
python manage.py runserver
程序中获取配置项
如果在项目代码中需要获取settings中的配置项,这样获取:
1 | #切记不要导入具体的settings模块的路径,会形成高耦合 |
URL调度器-介绍
当一个用户请求Django站点的一个页面,下面是Django系统决定执行哪个Python代码使用的算法:
- Django确定要使用的根URLconf模块,一般是在settings中的ROOT_URLCONF设置的值,但是如果传入HttpRequest对象具有一个urlconf属性(由中间件设置),则其值将用于代替ROOT_URLCONF设置。
- Django加载该URLconf模块并查找变量urlpatterns,它是一个列表django.urls.path()和/或django.urls.re_path()实例。
- Django按顺序遍历每个URL模式,并停在与请求的URL匹配的第一个URL模式,需要特别注意编写的顺序
- 一旦某个URL模式匹配,Django就会导入并调用给定的视图,该视图是一个简单的Python函数(或基于类的视图方法)。该视图通过以下参数传递:
- 一个HttpRequest实例。
- 如果匹配的URL模式没有返回任何命名组,则来自正则表达式的匹配作为位置参数提供。
- 关键字参数由路径表达式匹配的任何命名部分组成,并由可选的kwargs参数传给django.urls.path()或django.urls.re_path()。
- 如果没有URL模式匹配,或者在此过程中的任何点发生异常,Django将调用适当的错误处理视图
URL调度器-基本使用
配置子应用urls.py
1 | from django.urls importpath |
注意
- 从URL中捕获值,请使用尖括号
- 捕获的值可以选择包含转换器类型。例如,用于int:name捕获,前面的int指整数参数,name是参数的名称
- 没有必要添加一个前导斜杠,因为每个URL都有,例如,使用articles而不是/articles
路径转换器
- str:匹配任何非空字符串,不包括路径分隔符’/‘。如果转换器不包含在表达式中,这是默认值。
- int:匹配零或任何正整数。返回一个int。
- slug:匹配由ASCII字母或数字组成的字符串,以及横线和下划线字符。例如:building-your-1st-django_site可以匹配,django_@site是不可以匹配的。
- uuid:匹配格式化的UUID。为防止多个URL映射到同一页面,必须包含破折号,并且字母必须是小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个UUID实例。
- path:匹配任何非空字符串,包括路径分隔符’/‘,可以匹配完整的URL路径,而不仅仅是URL路径的一部分str,使用时要谨慎,因为可能造成后续的所有url匹配都失效。
1
path('articles/<uuid:uuid>/',views.article_uuid),
1
2
3#获取uuid
import uuid
print(uuid.uuid1())
URL调度器所有使用方法
urls.py
1 | from django.contrib import admin |
自定义路径转换器
- 一个regex类属性,作为一个re匹配字符串
- to_python(self, value)方法,它处理匹配的字符串转换成要传递到视图函数的类型
- to_url(self, value)方法,用于处理将Python类型转换为URL中使用的字符串
使用正则表达式
正则表达辅助工具
使用正则表达式匹配路径,请使用re_path()而不是path()
在Python正则表达式中,命名正则表达式组的语法是(?P
注意事项
- 无论正则表达式匹配什么类型,每个捕获的参数都以字符串的形式发送到视图
- 除了命名的组语法,例如(?P
[0-9]{4}),也可以使用较短的未命名组,例如([0-9]{4}),但是不建议这样使用,会引起未知的匹配
错误处理
- handler400-状态码400
- handler403-状态码403
- handler404-状态码404
- handler500-状态码500
- 在settings中修改配置:
1
2
3DEBUG = False
ALLOWED_HOSTS = ['*'] - 在主应用的urls中配置:
1
handler404 = "polls.views.page_not_found"
- 在polls应用的views中添加函数page_not_found:
1
2def page_not_found(request,exception):
return HttpResponse('自定义的404错误页面') - 浏览器测试访问,找不到匹配的路由
URL调度器-URL反向解析
url调度器除了从用户发起请求,到匹配对应的view,还能在python程序中调用进行匹配,通过path或re_path中的name属性进行解析
- 在模板中,使用url模板标签
- 在Python代码中(主要是views),使用reverse()函数
示例
1 | from django.contrib import admin |
在模板中测试
- views.py跳转到页面
1
2
3
4
5
6
7
8
9from django.shortcuts import render, HttpResponse,HttpResponseRedirect
from django.urls import reverse
# Create your views here.
def index(request):
return HttpResponse("成功跳转到被反向解析的地方")
def index_page(request,page):
return HttpResponse(f"成功跳转到带参数的反向解析的地方,参数是{page}")
命名空间
命名空间主要用于配合url反向解析使用,多个不同的urls文件中可能配置同名的name,那么为了进行区分,给不同的urls进行不同的命名
注意
同一个项目下命名空间不能重复,切记!
命名空间基本使用
通过在url调度器的模块中,定义app_name = ‘polls’来命名
1 | from django.contrib import admin |
Django模型-介绍
模型,就是python中的类对应数据库中的表
ORM
ORM就是通过实例对象的语法,完成关系型数据库的操作的技术,是”对象-关系映射”(Object/Relational Mapping)的缩写
ORM把数据库映射成对象
示例
模型
1 | from django.db import models |
说明
- 模型类必须继承models.Model
- 每个属性对应数据库表中的一个字段
- 表名自动使用应用_类名的小写(如:polls_question),可以覆盖重写
- 如果模型类中没有指定primary_key,那么会自动创建一个id字段,自增,主键
Django模型-MySQL和sqlite3的数据库迁移
当编写了模型之后,需要将模型应用到数据库中,具体步骤如下:
- 创建项目model_study,及子应用model_app
1
2
3
4
5#创建项目
django-admin startproject model_study
#进入项目目录创建子应用
python manage.py startapp model_app - 配置应用,将模型对应的应用程序添加到项目的settings中:
1
2
3INSTALLED_APPS=[
'model_app'
] - 在settings.py中配置正确的数据库连接:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'USER': 'root',
'PASSWORD':'123456',
'HOST':'localhost',
'PORT':'3306',
'NAME': 'django_demo'
}
}
# sqlite3
import os
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR,'db.sqlite3'),
}
}注意
- 需要安装对应数据库的驱动
- pip install mysqlclient
- pip install pymysql
1
2
3#__init__.py
import pymysql
pymysql.install_as_MySQLdb()
- 需要在mysql数据库中创建数据库model_study
- 需要安装对应数据库的驱动
创建迁移
在项目根目录的cmd中运行:
1 | python manage.py makemigrations model_app #model_app是子应用的文件名 |
备注
- model_app是子应用的名称,如果不指定,那么就是对所有INSTALLED_APPS中的应用都进行预备迁移
- 指定该命令后,在对应的子应用下的migrations中会生成一个对应的迁移文件
正式迁移
1 | python manage.py migrate |
备注
没有添加子应用名,那么就会把django项目中所有的应用都迁移到数据库中
Django模型-更新数据库表结构
不管是新增模型,还是修改已有模型后,只需要执行行命令即可:
1 | python manage.py makemigrations model_app # 创建数据迁移 |
设置表名
1 | from django.db import models |
Django模型-逆向从数据库表生成模型类
- settings中设置好DATABASES配置
- 在对一个数据库中建立好表、约束和表关系等
- 在根目录的cmd中运行:
1
2
3python manage.py inspectdb > model_app/models.py
# model_app/models.py子应用的模型文件models.py- model_app是子应用名
- 第3步执行后会在models中生成对应的模型类
1
2
3
4
5
6
7
8
9
10
11
12
13
14from django.db import models
# Create your models here.
class Person(models.Model):
first_name = models.CharField(max_length=32)
last_name = models.CharField(max_length=32)
class Meta:
db_table = 't_person' #对应的数据库中的表名
def __str__(self):
return self.name
Django模型-字段介绍
模型类的属性对应数据库中表的字段,都是对应的Field类的实例
字段命名限制
- 字母,数字,下划线,首字母不能是数字
- 字段名称不能是Python保留字
- 由于Django查询查找语法的工作方式,字段名称不能在一行中包含多个下划线,譬如“abc__123”就是不允许的,一个下划线是可以的,如:’first_name’
主键的使用
默认会自动创建一个自增,主键的id列
如果指定了primary_key为其它列,那么不会自动创建id列
例如:
1 | id = models.AutoField(primary_key=True) |
常见的字段
| 字段名 | 作用 |
|---|---|
| AutoField | 自增一个IntegerField,根据可用的ID自动递增 |
| BooleanField | 该字段的默认表单部件是checkbox,默认值是None |
| CharField | 一个字符串字段 |
| DateField | 一个日期,在Python中用一个datetime.date实例表示 |
| DateTimeField | 一个日期和时间,在Python中用一个datetime.datetime实例表示 |
| FloatField | 在Python中用一个float实例表示的浮点数 |
| SmallIntegerField | 就是一个IntegerField,-32768到32767的值 |
| IntegerField | 一个整数。从-2147483648到2147483647的值 |
| TextField | 一个大的文本字段。该字段的默认表单部件是一个Textarea |
特别的说明
1 | impor tuuid |
常见的属性
- max_length:字段最大长度,用于字符串等,字符串类型CharField必须设置该值
- null:如果True,Django将在数据库中存储NULL空值。默认是False
- blank:如果True,该字段被允许为空白(“”)。默认是False。
注意
这不同于null。null纯粹是与数据库相关的,而blank与验证相关。如果一个字段有blank=True,表单验证将允许输入一个空值。如果一个字段有blank=False,该字段将是必需的 - choices:
示例:YEAR_IN_SCHOOL_CHOICES = ((‘FR’, ‘Freshman’),(‘SO’,’Sophomore’),(‘JR’, ‘Junior’),(‘SR’, ‘Senior’),(‘GR’, ‘Graduate’)) ,中文示例:SEX_CHOICES=((1, ‘男’),(2, ‘女’))元组中的第一个元素是将存储在数据库中的值,第二个元素是将在页面中显示的值,最常见用于下拉选择框select - default:字段的默认值
- help_text:用于显示额外的“帮助”文本
- primary_key:如果True,这个字段是模型的主键,默认是False
- unique:如果True,该字段在整个表格中必须是唯一的
- verbose_name:详细字段名,不指定则是属性名的小写,并且用空格替换’_’





