Django教程
环境搭建
安装虚拟环境
1 | 安装虚拟环境 |
创建虚拟环境
1 | 创建虚拟环境 |
安装包
1 | 安装包需要进入对应的虚拟环境,则安装的包内容只作用于该虚拟环境 |
Django初始化
创建项目
1 | 创建django项目,前提:必须进入到虚拟环境下 |
项目结构
- __init__.py:说明Django3是一个包
- settings:项目的配置文件,如数据库的配置
- urls.py:进行url路由的配置
- wsgi.py:web服务器和Django交互的入口
- manage.py:项目的管理文件,通过该文件可以管理整个django的项目
创建应用
1 | 在django中,一个项目由多个应用组成,每个应用完成一个特定的功能 |
应用结构
- __init__:标识booktest是一个包
- models.py:数据库相关的操作
- views.py:接受请求并进行处理,与model和templete及逆行交互。它定义处理函数,每个页面对应一个处理函数
- test.py:写测试代码的文件,目前不需要开发去写
- admin.py:负责网站管理后台
应用与项目关联
1 | # 开发项目前需要将创建的应用与项目之间建立关系,则需要对应用进行注册 |
启动项目
1 | 位于项目的根目录下 |
Django基本使用
ORM框架
1 | # O:Object,R:数据库,M:映射 |
模型
创造模型类
设计模型类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 操作对应的应用下的models.py文件
# django会自动的生成表的主键ID
from django.db import models
# 创建的类必须要继承models.Model类
class BookInfo(models.Model):
'''创建一个bookinfo的类,回头会创建一个【应用名_bookinfo】的表'''
# charField:表示创建的字段是字符类型,max_length表示该字段的字符长度
btitle = models.CharField(max_length=256)
# DateField:表示创建一个日期格式的表
bpub_date = models.DateField()
# BooleanField:表示布尔类型,default表示该字段的默认值
bgender = models.BooleanField(default=False)
# IntegerField:表示整数类型
bread = models.IntegerField(default=0)
# Foreign:创建外键,内部参数是外键对应的类名,数据库中生成的外键名为【关系属性名_id】
# on_delete:外键创建的时候要添加的参数
hook = models.ForeignKey("Book", on_delete=models.CASCADE)创造迁移文件
1
2迁移文件是根据models.py文件生成的
python manage.py makemigrations执行迁移生成表
1
2会自动根据生成文件生成对应的数据库中的数据表
python manage.py migrate数据库配置
1
2
3
4
5
6
7# 数据库配置在项目的settings.py文件中,默认为sqllite3
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
模型类操作数据表
进入项目的shell
1
python manage.py shell
操作数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44# 导入模型类,从应用的【models.py】文件中导入对应的类名
from bookinfo.models import BookInfo
from datetime import date
# 插入数据
ob = BookInfo() # 创建对象
ob.btitle = "帅" # 添加对象的实例属性
ob.pub_date = date(1992,2,15)
ob.save() # 实例属性修改完毕后,save即可修改
# 查询数据,通过【类名.objects.get(查询条件)】返回对象,然后直接打印出对象的实例属性即可
b2 = BookInfo.objects.get(id=1)
b2.btitle
# 修改数据,先获取数据对象,然后修改其属性后,再save()
b2 = BookInfo.objects.get(id=1)
b2.btitle = "霸气"
b2.save()
# 删除数据,先获取数据对象,调用delete()
b2 = BookInfo.objects.get(id=1)
b2.delete()
# 查询表中所有的数据
BookInfo.objects.all()
# 添加外键,先获取外键指向的主键对象,然后将外键字段的属性设置为主键对象
b = Book.objects.get(id=1)
fb = BookInfo.objects.get(id=2)
fb.hook = b
fb.save()
# 访问外键的ID,其字段为:外键名_id
b = BookInfo.objects.get(id=1)
b.hook_id
# 访问外键指向的对象
b = BookInfo.objects.get(id=1)
foreign_obj = b.hook
foreign_obj.btitle # 访问外键对象的标题
# 访问一张表中,关联主键的所有外键的内容,
b = Book.objects.get(id=1)
b.bookinfo_set.all() # 获取到该外键的所有对象
django后台管理
本地化,修改项目【settings.py】文件中如下内容:
1
2LANGUAGE_CODE = 'zh-hans' # 设置语言
TIME_ZONE = 'Asia/Shanghai' # 设置时区创建管理员
1
python manage.py createsupperuser
注册模型类,在应用【admin.py】下注册模型类,告诉django框架根据注册的模型类生成对应表的管理页面
1
2
3
4
5
6
7from django.contrib import admin
# 需要将models.py中的类导入到模块下
from wuxiang.models import Book
# 将数据库中表对应的类注册到【应用】对应的admin.py文件中
# 模型类不可重复注册
admin.site.register(Book)自定义模型类,自定义admin管理页面的显示参数
1
2
3
4
5
6
7
8
9
10
11from django.contrib import admin
from wuxiang.models import Book, Hero
# Register your models here.
class BookAdmin(admin.ModelAdmin):
'''定义图书模型管理类,类名格式:【models.py类名+Admin】'''
'''list_display:列表中填写的是数据库中对应的列名'''
list_display = ['btitle', 'bcontent', 'bpub_date']
# 自定义注册的页面,同时需要添加自定义的模型管理类
admin.site.register(Book, BookAdmin)(自定义模型修改更好)修改admin管理页面表详情页面数据的显示,通过修改models.py对应数据类中的__str__()方法的打印值
1
2
3
4
5
6
7
8
9
10from django.db import models
class Book(models.Model):
btitle = models.CharField(max_length=256)
bcontent = models.CharField(max_length=256)
bpub_date = models.DateField()
# 修改数据类的__str__()中的返回值
def __str__(self):
return self.btitle
视图
访问配置
在django中,通过浏览器去请求一个页面,使用视图函数来处理这个请求,视图函数处理完以后,给浏览器返回页面内容
定义视图函数
1
2
3
4
5
6
7
8# 在【应用】下的【views.py】文件中定义视图函数
# 本质是对用户请求的链接进行处理,并返回响应的数据
# 视图函数需要返回内容,必须通过HttpResponse对象
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("返回给页面的内容")url路由配置,建立url地址和视图的对应关系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# 配置的地方有两个,一个是项目下的【urls.py】(已自动创建),一个是应用下的【urls.py】(需要手动创建)
# 应用下的【urls.py】,是具体的路径配置,内容如下:
from django.conf.urls import url
from wuxiang import views
urlpatterns = [
# url的方法是1.x版本的django方法,现在都适用path方法
url('^index$', views.index),
# 正则中用括号包裹分组,则在匹配的时候会将分组匹配的内容传递给视图函数
url('^index/(\d+)$', views.index),
]
# 项目下的【urls.py】是总的路由配置,用于汇总app下的路由配置,内容如下:
# path函数并不支持正则表达式,如果要支持正则表达式,则可使用re_path方法
from django.contrib import admin
from django.urls import path, include, re_path
urlpatterns = [
path('admin/', admin.site.urls),
# 第一个参数是正则,第二个参数是app的路由配置文件
# 此处匹配符合的内容会从url中去除, 然后会拿剩余的字段到app对应的文件中进行匹配
re_path('a/\d+', include('wuxiang.urls')) # 导入app下路由配置文件
]
重定向配置
复杂写法
1
2
3
4
5
6
7# 重定向配置需要用到HttpResponseRedirect
from django.http import HttpResponseRedirect
def wuxiang(request):
# HttpResponseRedirect表示重定向
# 第一个参数:重定向后访问的域名
return HttpResponseRedirect('/index')精简写法
1
2
3
4
5# 利用redirect函数重定向
from django.shortcuts import render, redirect
def wuxiang(request):
# 第一个参数:重定向后访问的域名
return redirect('/index')
模板
创建模板文件夹
1
2在项目的根目录下创建一个文件夹templates
touch templates配置模板目录,在项目的配置文件【settings.py】中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 注意修改其中的【DIRS】配置项
# 为了便于区分模板被用于哪个App,我们会在templates文件夹中创建与app同名的文件夹,用于存放该App的模板
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 配置模板的具体目录位置
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]创建模板文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28# 在对应App的模板文件夹中创建html格式的模板文件
<html lang="en">
<head>
<meta charset="UTF-8">
<title>这是一个模板文件</title>
</head>
<body>
<h1>有本事你就来呀</h1>
<h2>{{ content }}</h2>
<h3>模板中循环列表内容进行展示</h3>
<ul>
{# 将for循环语句包裹在{% 循环语句 %} #}
{% for i in list %}
{# 循环的变量:{{ 变量名 }} #}
<li>{{ i }}</li>
{# 当循环对象为空时则会执行empty下面的语句 #}
{% empty %}
<li>没有英雄的信息</li>
{% endfor %}
{# 结尾需要表示{% endfor %} #}
</ul>
<!-- 开发时,a标签的href中内容不加/,则会直接在原url后直接拼接,导致报错,正确的做法是以/开头 -->
<a href="/index">内容</a>
</body>
</html>使用模板文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 在对应app的models.py文件中进行定义
from django.http import HttpResponse
# 加载和编辑模板时,需要以下两个函数
from django.shortcuts import render
from django.template import loader
def index2(request):
# 加载模板文件,参数是对应模板文件的路径,该路径是相对于templates文件夹路径而言的
temp = loader.get_template('wuxiang/index.html')
# 定义模板上下文:给模板文件传递数据, 内容可以是字符串、列表等
content = {"content": "姓名区域", 'list':list(range(1,10))}
# 模板渲染:返回完整的html内容
# 格式:模板对象.render(模板上下文)
res_html = temp.render(content)
return HttpResponse(res_html)1
2
3
4
5
6
7
8
9
10
11
12
上述内容也可以简写
```python
# 利用gender函数可以一次性生成对应的html返回内容
from django.shortcuts import render
def index2(request):
# 第一个参数:request
# 第二个参数:模板文件的路径
# 第三个参数:模板文件中各参数对应的值所组成的字典数据
return render(request, 'wuxiang/index.html', {"content": "姓名区域", "list": list(range(1, 10))})
模型详解
配置数据库
安装pymysql模块
1
pip install pymysql
修改django的项目文件【__init__.py】文件,导入pymysql的模块
1
2
3
4
5
6# 修改项目文件夹下的__init__.py文件,不导入的话,项目启动报错
# 也有可能让安装mysqlclient
import pymysql
# 2,0,1是数据库版本
pymysql.version_info = (2, 0, 1, 'final', 0)
pymysql.install_as_MySQLdb()修改django项目配置文件【settings.py】文件中的数据库链接方式
1
2
3
4
5
6
7
8
9
10
11
12DATABASES = {
'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
'ENGINE': 'django.db.backends.mysql',
# 'NAME': BASE_DIR / 'db.sqlite3',
'NAME': 'django', # 数据库的名称,需要提前创建好
'USER': 'root', # 数据库的登录用户名
'PASSWORD': 'qwer1234', # 数据库的登录密码
'HOST': '192.168.85.131', # 数据库所在的服务器IP
'PORT': '3306', # 数据库的连接端口号
}
}
模型类属性
模型类属性定义格式
1
2
3
4# 每修改一次模型类属性的结构,就都需要重新生成迁移文件和迁移表,除了null和blank属性
from django.db import models
属性名 = models.字段类型(选项)模型类属性名限制
- 不能是python的保留关键字
- 不允许连续的下划线
- 定义属性的时候需要指定字段类型,通过字段类型的参数指定选项
字段类型种类
类型 描述 AutoField 自动增长的IntegerField,通常无需指定,不指定的时候Django会自动创建属性名为id的自动增长属性 BooleanField 布尔字段类型,值为True、False NullBooleanField 支持Null、False、True三种数据类型 CharField(max_length=最大长度) 字符串,参数max_length表示最大字符个数,是一定需要设定的 TextField 大文本字段,一般超过4000字 IntegerField 整数 DecimalField(max_digits=None, decimal_places=None) 十进制浮点数,参数max_digits表示总的位数,decimal_places表示小数的位数 FloatField 浮点数,参数同上。该属性的字段相比较DecimalField而言精确度低 DateField(auto_now=False) 日期,表示年月日。
auto_now参数表示更新该字段的修改时间为当前时间,每修改一次都会更新,默认为False。
auto_now_add参数表示第一次创建时更新该字段的时间为当前时间,此后修改便不会更新该字段,默认为False。
auto_now和auto_now_add属性互斥,不可同时设定TimeField 时间,表示时分秒,参数同上 DateTimeField 日期+时间,参数同上 FileField 上传文件字段 ImageField 继承于FileField,对上传的内容进行校验,确保是有效的图片 选项
选项名 描述 default 设置默认值。该属性无需修改表结构 primary_key 设置主键,默认为False,一般与AutoField一起使用 unique 唯一性约束,默认为False,若为True,则表示字段的内容必须唯一 db_index 字段建立索引,默认为False。若为True,则会为该字段建立索引 db_column 自定义数据库中字段的名称,如果为指定则使用属性的名称 null 字段是否可以为空,默认False,若为True,表示允许为空 blank 表示字段是否允许为空白,默认为False,若为True,表示允许为空白。该属性无需修改表结构 null属性是数据库中约束的范畴,blank是django后台约束的范畴
查询操作
配置数据库日志
1 | 修改mysql的配置文件,打开general_log_file |
查询函数
使用格式:
1
2
3# 数据表的查询方式
# 当返回结果为查询集合时,可直接在后面直接调用方法
模型类.objects属性.方法(筛选条件).方法(筛选条件)方法分类
方法 功能 get 返回表中满足条件的一条且只能一条的数据, 是一个模型对象。参数写查询条件
查询返回多条数据,返回异常:MultipleObjectsReturned。
查询无符合条件的数据,返回异常:DoesNotExist。all 返回模型类对应表中的所有数据,返回的是一个查询集(QuerySet类型) filter 返回满足条件的数据,参数写查询条件,返回值是查询集(QuerySet类型) exclude 返回不满足条件的数据,参数写查询条件,返回值是查询集(QuerySet类型) order_by 对查询结果进行排序,参数中填写根据那些字段进行排序,返回值是查询集(QuerySet类型) order_by排序案例:
1
2
3
4
5
6# 按照id降序排列(字段前加-号),read升序排列
BookInfo.objects.all().order_by('-id', 'read')
BookInfo.objects.order_by('-id', 'read') # 对所有数据进行操作时,都可省略all()
# 根据筛选数据进行排序
BookInfo.objects.filter(bpub_time__gt=date(1992,6,25)).order_by('bpub_time')筛选条件分类,适用于filter、exclude、get方法
1
2# 条件的编写格式
模型类属性名__条件名=值条件名 作用 exact 判定等于,也可直接省略该条件名。【字段名__exact=1】 contains 模糊查询,包含。【字段名__contains=’帅’】 startswith 模糊查询,开头。【字段名__startswith=’shuai’】 endswith 模糊查询,结尾。【字段名__endswith=’shuai’】 isnull 空查询,判定是否为空。【字段名__isnull=True】 in 范围查询。【字段名__in=[1, 2, 3]】 gt、lt、gte、lte 比较查询。gt(大于)、lt(小于)、gte(大于等于)、lte(小于等于)。【字段名__gt=3】 year 日期查询,也可不使用year,直接使用字段跟日期比较。【字段名___year=1998】 逻辑比较
1
2
3
4
5
6
7
8
9
10
11
12
13# Q对象:用于查询时条件之间的逻辑关系。not and or,可以使用Q对象进行&|~
# 使用前需导入
from django.db.models import Q
# 与关系:Q(条件)&Q(条件)
BookInfo.objects.filter(id_gt=3, id_lt=6)
BookInfo.objects.filter(Q(id_gt=3)&Q(id_lt=6))
# 或关系:Q(条件)|Q(条件)
BookInfo.objects.filter(Q(id_gt=3)|Q(id_lt=6))
# 非关系:~Q(条件)
BookInfo.objects.filter(~Q(id_gt=3))属性比较
1
2
3
4
5
6
7# F对象:用于类属性之间的比较
# 使用前需要导入
from django.db.models import F
# 将比较的属性放在F对象中
# 查询图书阅读量大于两倍评论量的数据
BookInfo.objects.filter(bread__gt=F('bcomment')*2)聚合函数:aggregate
1
2
3
4
5
6
7
8
9
10
11
12
13# 格式:筛选.aggregate(聚合函数(字段名))
# 使用前,需导入会用到的聚合类
from django.db.models import Sum, Count, Max, Min, Avg
# 对查询结果进行聚合前需要先调用aggregate进行聚合,结果返回值是一个字典,主键名为:字段名__聚合类(小写)
# 获取id大于6的所有id和,查询返回结果为:{"id__sum": 100}
BookInfo.objects.filter(id_gt=6).aggregate(Sum('id'))
# 获取id大于6的数据总数
BookInfo.objects.filter(id_gt=6).aggregate(Count('id'))
# 只获取数据总量值的话,聚合部分可直接用count()代替
BookInfo.objects.filter(id_gt=6).count()
查询集
查询集合特性
惰性查询
只有在实际使用查询集中的数据的时候,才会对数据库进行真正的查询
缓存
当使用同一个查询集的时候,第一次会发生实际数据库的查询,然后将查询结果缓存起来,之后再使用这个查询集时,使用的是缓存中的结果
限制查询集
1 | # 可以使用切片和下标对查询集进行限制 |
备注
数据库忘记密码
1 | 若数据库密码忘记,则在mysql配置文件中添加如下内容重启登录 |
Image的base64存放
1 | // image转base64的网站:http://tool.chinaz.com/tools/imgtobase/ |