Django学习笔记
1 Django的快速入门
1.1 模型类的设计和表生成
1.1.1 模型类
- 设计的类放到
app
里面的models.py
,并且要继承django.db.models.Model
类,示例如下: - 字段规范:
字段名=models.字段类型(属性=XX)
from django.db import models
class MyModel(models.Model):
name = models.CharFild(max_length=10)
1.1.2 表生成
- 生成迁移文件:
python manage.py makemigrations
- 执行迁移生成表:
python manage.py migrate
1.2 通过模型类操作数据表
- 模型类的对象中有一个叫
save
的方法,如果使用save
方法,该对象会被保存到数据库中的对应表格内或者更新 - 模型类对象的
delete
方法可以删除对应的数据 - 模型类对象的
object
字段可以用于进行数据库的查询
from appname.models import MyModel
# 准备阶段
save_test = MyModel()
save_test.name = '保存测试'
delete_test = MyModel()
delete_test.name = '删除测试'
# 添加
save_test.save()
delete_test.save()
# 查询
search_result = MyModel.object.get(name='删除测试')
# 修改
update_result = MyModel.object.get(name='保存测试')
update_result.name = '更新测试'
update_result.save()
# 删除
delete_result = MyModel.object.get(name='删除测试')
delete_result.delete()
1.3 模型类关系和关系查询
1.3.1 模型类关系
- 一对多关系: 在多方的类中加入字段=>
字段名=models.ForeignKey('类名称')
,在使用时可以将外键字段直接用外键对象赋值 - 一对象获取多对象:
一对象.外键字段名称
- 多对象获取所有一对象:
多对象[类名要小写].一对象_set.all()
from django.db import models
class OneForeighKeyTest(models.Model):
name = models.CharFild(max_length=10)
class ManyForeighKeyTest(models.Model):
name = models.CharFild(max_length=10)
one = models.ForeighKey('OneForeighKeyTest')
from appname.models impor OneForeighKeyTest, ManyForeighKeyTest
# 一获取多
one = OneForeighKeyTest.object.get()
many_result = one.manyforeighkeytest_set.all()
# 多获取一
many = ManyForeighKeyTest.object.get()
one_result = many.one
1.4 Django后台管理(ip:端口/admin)
- 语言和时区的本地化(通过修改setting.py进行实现):
LANGUAGE_CODE='zh-hans'
TIME_ZONE='Asia/Shanghai'
- 创建管理员:
python manage.py createsuperuser
- 注册模型类: 在
app
下的admin.py
中添加django.contrib.admin.site.register(模型类)
- 自定义管理页面: 在在
app
下的admin.py
中添加[类名]Admin
类,继承admin.ModelAdmin
,
在[类名]Admin
类中添加列表字段list_display
,内容为[类名]里的字段名
,并在register方法中添加[类名]Admin
类名作为第二个参数
from django.contrib import admin, ModelAdmin
from appname.models import MyModel
class MyModelAdmin(ModelAdmin):
list_display = ['name', ...]
admin.site.register(MyModel, MyModelAdmin)
1.4 视图
- 视图函数的定义: 视图函数通常定义在
view.py
文件里,且必须含有参数request
,它是HttpRequest
类型的数据,视图函数需要返回一个HttpResponse
对象。
from django.http import HttpResponse
def index(request, [后面可以配合括号捕捉参数]):
return HttpResponse(‘这是首页’)
# 重定向
from django.http import HttpResponseRedirect
from django.shortcut import redirect
def redict_one(request, [后面可以配合括号捕捉参数]):
return HttpResponseRedirect(‘跳转的网页’)
def redict_two(request, [后面可以配合括号捕捉参数]):
return redirect('跳转的网页')
- 配置url,建立url和视图的映射关系: 在
urls.py
文件里添加urlpatterns
列表,里面的值为url('网页url',对应的视图函数[注意,视图函数不要加括号])
或者url('网页url',include(app名称.urls.py))
- 通过url传递参数: url(
网页url正则(参数正则)网页url正则
, 视图函数),可以有多个参数,它会依次在传递给视图函数中request
后面的参数
from django.urls import path, include
urlpatterns = [
# 可以有多个参数,参数会按照顺序从前往后传递给视图函数requet后面的参数
path('^正则(参数正则)正则$', 视不加括号的图函数),
path('^', include(’别的urls文件‘)),
]
1.5 模板
1.5.1 手动方式
- 配置模板路径文件夹: 在
setting.py
的TEMPLATES
的DIRS
键对应的列表中添加文件夹的路径
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [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',
],
},
},
]
- 加载模板文件:
django.template.loader.get_template(HTML文件路径)
- 定义上下文,传递数据进入模板文件:
RequestContext(request, {键值对)
- 模板渲染并返回客户端:
return HttpResponse(模板对象.render(上下文对象))
from django.http import HttpResponse
from django.template import loader, RequestContext
def template_one(request):
model = loader.get_template(HTML文件路径)
context = RequestContext(request, {键值对)
html = model.render(context)
return HttpResponse(html)
1.5.2封装方式
from django.shorcut import render
def template_two(request):
return render(request, HTML路径, context={键值对})
1.5.3 html文件内的布置
- 普通变量的使用: {{
context的键
}} - 循环语句的使用:
{% for i in 列表对应的键 %}
{{ i[在这里,i代表列表的某个值] }}
{% endfor %}
- 对象变量的使用: {{
对应键.字段名
}} - 列表变量的使用: {{
对应键.下标
}}或者用循环
2 模型详解
2.1 Django连接Mysql数据库
在setting.py文件中配置如下内容
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
# 使用的数据库要实现建立好,Django不能自动建立数据库
'NAME': '使用的数据库名称',
'USER': '用户名',
'PASSWORD': '密码',
'HOST': 'IP地址',
'PORT': 端口号,
}
}
在__init__.py中导入mysql包
import pymysql
# 如果有版本错误,就把下面一行取消注释
# pymysql.version_info = (1, 4, 13, 'final', 0)
pymysql.install_as_MySQLdb()
2.2 模型类字段、属性及其约束
字段名称的限制:
- 不能是python保留关键字
- 不能使用连续的下划线
- 需要指定字段的类型,语法为:
字段名 = models.字段类型(属性)
from django.db import models
AutoField:自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性。
BooleanField:布尔字段,值为True或False。
NullBooleanField:支持Null、True、False三种值。
CharField(max_length=字符长度):字符串,
参数max_length表示最大字符个数。
TextField:大文本字段,一般超过4000个字符时使用。
IntegerField:整数。
DecimalField(max_digits=None, decimal_places=None):十进制浮点数,
参数max_digits表示总位数,
参数decimal_places表示小数位数。
FloatField:浮点数。
DateField[auto_now=False, auto_now_add=False]):日期。
参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false。
参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false。
参数auto_now_add和auto_now是相互排斥的,组合将会发生错误。
TimeField:时间,参数同DateField.
DateTimeField:日期时间,参数同DateField。
FileField:上传文件字段。
ImageField:继承于FileField,对上传的内容进行校验,确保是有效的图片。
约束
通过选项实现对字段的约束,选项如下:
null:如果为True,表示允许为空,默认值是False。
blank:如果为True,则该字段允许为空白,默认值是False。
对比:null是数据库范畴的概念,blank是表单验证证范畴的。
db_column:字段的名称,如果未指定,则使用属性的名称。
db_index:若值为True, 则在表中会为此字段创建索引,默认值是False。
default:默认值。
primary_key:若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用。
unique:如果为True, 这个字段在表中必须有唯一值,默认值是False。
2.3 查询函数
通过模型类.objects
属性可以调用如下函数进行查询:
get 返回满足条件的一条数据,返回的是一个模型类的对象
如果查询到多个数据就会抛出MultipleObjectsReturned
如果没查到则抛出DoesNotExists
all 返回模型类的全部数据,返回类型是JquerySet
filter 返回满足条件的数据,返回类型是JquerySet
exclude 返回不满足条件的数据,返回类型是JquerySet
order_by 排序,返回类型是JquerySet
按照id从小到大排序 order_by('id')
按照id从大到小排序 order_by('-id')
查询的条件
条件格式:模型类属性名__条件名=值
判等条件名 exact
包含 contains
开头以 startwith
结尾以 endwith
空查询 isnull,例如 Book.objects.filter(name__isnull=True)
范围查询 in,例如 Book.objects.filter(name__in=['TCP协议', 'IP协议'])
大于小于等于 gt(greate than)大于 lt(less than)小于 gte 大于等于 lte 小于等于
日期查询 year 年 month 月 day 日 gt 日期大于...
2.4 Q对象,实现多条件查询
作用: 用于条件多条件查询,每一个Q对象都封装一个条件,Q对象之间用&(与)|(或)~(非)
from django.db.models import Q
# id不等于1或name包含c的数据
Book.objects.filter(~Q(id__exact=1) | name__contins='c')
2.5 F对象,实现属性之间的比较
作用: 用于类属性之间的比较
from django.db.models import F
# id大于等于1或count两倍的数据
Book.objects.filter(Q(id__gte=2*F('count')))
2.6 聚合函数
作用: 对查询结果进行聚合操作
sum
count
avg
max
min
agreegate
: 调用这个函数来使用聚合,返回一个字典。
from django.db.models import Count
from appname.models immport Book
# 获取图书的数量
Book.objects.all().agreegate(Count('id'))
2.7 查询集相关
- 查询集是惰性的,直接查询是不会查询的,只有使用后才会发生查询
- 如果查询内容和前面的一样,则会返回缓存的数据
- 查询集可以切片或用下表取数据,但下标不能为负数
exist
方法可以判断查询集是否有数据
2.8 模型类关系
- 一对多关系,班级对学生关系,`s_class=ForeignKey(‘Class’)
- 多对多,在任何一个中定义即可,ManyToManyField(‘类名’)
- 一一对应,在任何一个中定义即可,OneToOneField(‘类名’)
2.9 一对多的关联查询
在这里,我们定义一对应的类叫一类
,多对应的类叫多类
,多类中建立关联的属性叫关联属性
由一类对象查询多类:一类的对象.多类类名小写_set.all()
由多类对象查询一类:多类对象.关联属性
有多类对象查询一类id:多类对象.关联属性_id
通过模型类实现关联查询:
查询生,要求学生关联的班级名称包含'信科'1班:
Student.objects.filter(class__name__contains='信科1班')
2.10 插入、更新、删除
插入、更新模型对象用save()
方法,删除模型对象用delete()
方法
2.10 自关联
自关联是特殊的一对多,格式为 ForeignKey('self', null=True, blank=True)
2.11 管理器objects
- objects到底是什么
objects是models.Manager对象,如果自定义管理器,那么Django将不会自动生成管理器
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=10)
object = models.Manager() # object是用来替换objects的对象,值为Manager或Manager的子类对象
- 重写models.Manager对象有什么用?
可以自定义查询方式,通过子类继承、覆盖重写想要定制的方法即可完成 models.Manager
有一个叫做model
的方法,返回models.Manager
所在类的类名
2.12 元选项
在模型类中添加内部类Mate
from django.db import models
class MyClass(models.Model):
title = CharField(max_length=10)
class Meta:
db_name = [指定table name]
3 视图详解
3.1 视图的使用
- 视图函数的定义:
request
参数必须有,是一个HttpRequest对象,参数名可以改,但是不建议改。 - 配置
url
,建立视图函数和url
之间的映射关系,通常在urls.py
文件中通过urlpatterns
列表建立映射。
from django.urls import path, include
from user import views
urlpatterns = [
path('^正则$', '视图函数'),
path('^正则(正则参数1)正则(正则参数2)正则$', '视图函数'),
path('^正则', include('urls文件')),
path('^正则/', include('urls文件')),
path('^正则/$', include('urls文件')),
]
3.2 错误的视图
- 404视图错误
在templates的根目录下建立404.html即可修改默认的404页面,
django自动调用404.html时候,会传递一个request_path的模板变量.
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>自定义的404页面</title>
</head>
<body>
页面{{ request_path }}找不到!
</body>
</html>
- 500错误
在视图函数出错误时会抛出500异常,需要建立一个500.html
文件在templates
下.
3.3 捕获url参数
进行url匹配的时候,可以把要的参数写成一个正则表达式组,django会自动捕捉参数传递给视图函数。
- 位置参数
按照参数的先后顺序把参数传递给视图函数
/goods_book/001.html,要求匹配type book以及id 001
urlpatterns = [
url('^book_(\w+)/(\d+).html', 'index')
]
def index(request, type, id):
return HttpResopnse('XXX')
- 组参数
可以通过指定参数名传递参数,正则表达式组格式为?P<变量名>正则
/goods_book/001.html,要求匹配type book以及id 001
urlpatterns = [
url('^book_(?P<type>\w+)/(\d+).html', 'index')
]
def index(request, type, id):
return HttpResopnse('XXX')
3.4 视图函数的request对象
request
是HttpRequest
对象,包含了请求的信息.
- request.GET: 存储GET请求的参数,request.POST: 存储POST请求的参数
- 他们可以通过字典的方式取数据或用get方法取数据,如果没有那个键值对,字典的方法会抛出KeyError,get方法会返回None,如果get方法设置了默认值,则会返回指定的默认值.
def index(request):
request.GET.get('username', '默认值') # 如果没指定默认值,默认值为None;如果键值对不存在,则返回默认值.
try:
request.GET['password']
exccept KeyError as e: # 如果键值对不存在则抛出KeyError
print(e)
3.5 Ajax异步请求
ajax请求的格式
$.ajax({
'url': 请求的url地址,
'type': 请求的方式, // POST/GET
'dataType': 预期返回数据的格式,
'data': 参数,
'success': (function(data){
// 请求成功的回调函数,data是返回的数据
})
})
- js文件是静态文件,需要在
setting.py
中配置静态文件的地址
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
- 示例
<script>
$(function(){
// 准备阶段
var username = 'username';
var password = 'password';
// 绑定事件
$('#id').click(function() {
$.ajax({
'url': '/check',
'type': 'post', // POST/GET
'dataType': 'json',
'data': {'username': username, 'password': password},
}).success(function(data){
请求成功的回调函数,data是返回的数据
})
})
})
</sctipt>
- ajax异步请求
ajax参数添加async
,true
为异步,false
为同步
3.6 Cookie与Session
- 设置
Cookie
response.set_cookie('键', 值) # 退出浏览器后销毁cookie
response.set_cookie('键', 值, max_age=X(单位:秒))
response.set_cookie('键', 值, max_age=, expires=datatime(在指定的datetime后销毁cookie))
- 读取Cookie和读取POST,GET的方法一样
- response.delete_cookie(‘键’) # 删除指定的cookie
- 设置同样的键名可以覆盖原先的cookie
- 设置Session
request.session['键']=值
-
看一下session是否有指定的键:
request.session.has_key('键')
-
读取session和GET一样
-
清除所有的session的值:
request.session.clear()
-
清除所有的session:
request.session.flush()
-
清除指定的session:
del request.session['键']
-
设置session过期时间:
request.session.set_expiry(value)
request.session.set_expiry(3900) # 3900后销毁session
request.session.set_expiry(0) # 退出浏览器后销毁session
request.session.set_expiry(None) # 两周后销毁session
4 模板详解
模板可以产生html,控制页面展示的内容,模板文件不仅仅是一个html文件
模板文件包含两部分:
- 静态内容
html,css,js
- 动态内容,通过模板语言动态生成
html
代码
4.1 模板文件的使用
- 加载模板文件,得到加载对象
- 创建上下文对象,填充上下文
- 加载对象都调用render函数,把加载对象和上下文结合起来,生成html
- 封装HttpResponse
from django.http import HttpResponse
from django.template import loader, RequestContext
def template_one(request):
# 加载模板文件,得到加载对象
model = loader.get_template(HTML文件路径)
# 创建上下文对象,填充上下文
context = RequestContext(request, {键值对)
# 加载对象都调用render函数,把加载对象和上下文结合起来,生成html
html = model.render(context)
# 封装HttpResponse
return HttpResponse(html)
4.2 模板文件加载顺序
- 首先去配置的模板目录下寻找模板文件
- 让后再去
INSTALL_APPS
列表的目录(该目录下必须要有templates
文件夹,否则会跳过该目录)从前往后寻找模板文件
4.3 模板语言
4.3.1 模板变量
模板变量由数字,字母,小数点组成,下划线构成,不能以下划线开头
使用模板变量{{ 模板变量 }}
如何解释{{ book.title }}
按照从上向下的顺序一次尝试,尝试成功一次后就把它当作尝试成功的内容
1) 把book当作字典,book.title等价于book['title']
2) 把book当作对象,book.title等价于book对象的title属性值
3)把book当作对象,book.title等价于title对象的title方法返回值
如何解释{{ book.0 }}
按照从上向下的顺序一次尝试,尝试成功一次后就把它当作尝试成功的内容
1) 把book当作字典,book.title等价于book['0']
1) 把book当作列表,book.title等价于book[0]
如果解析失败会怎么样?
如果解析失败,会用暂时用空值代替
4.3.2 模板标签
格式:{% 代码段 %}
for
循环
{% for i in 列表 %}
for语句执行片段
当前执行循环第{{ forloop.counter }}}次
{% endfor %}
if
条件判断
{% if 条件 %}
{% elif 条件 %}
{% else %}
{% endif %}
关系比较符
> < >= <= == !=
# 注意:在使用比较符时,比较符两边必须要有空格
逻辑运算
and or not
4.3.3 过滤器
过滤器用于对模板变量进行操作
格式: 模板变量 | 过滤器: 参数
参考内容见官方文档
- date 改变日期显示格式
- length 求字符串,列表,元组,字典长度
- default 设置模板的默认值
4.3.4 自定义过滤器
在app的根目录下创建名为templatetags
的python package
在templatetags
下创建py
文件,文件名随意
自定义过滤器参数至少一个,至多两个;使用过滤器时第一个参数默认选中的模板变量
from django.template import Library
# 名字随意
register = Library()
# 判断num是否为偶数
# @register.filter的功能时注册过滤器
@register.filter
def mod(num):
return num % 2 == 0
在html
文件里加载创建的py
文件
{% load 文件名 %}
4.3.5 模板语言的注释
单行注释
{# 注释内容 #}
多行注释
{% comment %}
{% endcomment %}
4.4 模板的继承
继承html文件
{% extends 'html文件路径' %}
定义块
{% block 块名 %}
{% endblock %}
子模板有父模板的全部内容,只需要对父模板的块覆盖重写即可
4.5 模板的转义
关闭转义的两种方法
1. 过滤器关闭
{{ 模板变量 | safe }}
2. 块过滤器关闭
{% autoescape %}
{% endautoescape %}
4.6 装饰器
def 函数名(view_func):
def wrapper(request, *args, **kargs):
# 进行判断了
# view_func代表掉哟个装饰函数的方法
return wrapper
@函数名
def index(request):
pass
4.7 csrf伪造
Django的csrf防伪只对post请求起作用,在表单中添加{{ csrf_token
}}即可
4.8 URL反向解析
在urls.py
的include
中添加namespace
,在url
中添加第三个参数name
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
# namespace
path('', include('user.urls', namespace='user')),
# 普通
path('index.html', view.index, name='index'),
# 参数不带名
path('show_(\w+)/(\d+).html', view.index, name='show'),
# 参数带名
path('show_(?P<type>\w+)/(?P<id>\d+).html', view.index, name='show'),
]
在模板的url配置时写
# 普通
{% url 'namespace:name' %}
# 例子
{% url 'user:index' %}
# 参数不带名
{% url 'namespace:name' 参数 %}
# 例子
{% url 'user:show' 'book', 1 %}
# 参数带名
{% url 'namespace:name' 字段=参数 %}
# 例子
{% url 'user:show' type='book', id=1 %}
在重定向的url
# 普通
reverse('namespace:name')
# 参数不带名
reverse('namespace:name', args=位置参数元组)
# 参数带名
reverse('namespace:name', kwargs=字典)
5 静态文件,中间件及后台
5.1 静态文件
Django
中,css
, js
, css
被成为静态文件
- 建立存放静态文件的文件夹
- 配置
setting.py
STATIC_URL = '/static/' # 静态文件的url
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
其他静态文件夹路径,
]
在模板文件中动态生成静态文件的url
{% load staticfiles %}
{% static '路径' %}
5.2 中间件
中间件函数时Django
预留给我们的可以干预请求和相应的函数接口,使用步骤如下:
在app
下新建middleware.py
定义中间件类
class 类名(object):
# 产生request,进行url匹配之前
def process_request(self, request):
pass
# 进行url匹配之后
def process_view(self, request, view_func, *args, **kw_args)
pass
# 处理请求,返回response之前
def process_response(self, request, response):
pass
# 异常处理
def process_exception(self, request, exception):
pass
中间件注册
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'自定义的中间件类',
]
5.3 后台管理系统
在setting.py
中本地化,指定时区
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
创建超管账号
python manage.py createsuperuser
模型类的相关设置字段
from django.db import models
class User(models.Model):
username = models.CharField(max_length=50, primary_key=True) # username
password = models.CharField(max_length=50) # password
class Mate:
db_table='指定的表名'
注册模型类
from django.contrib import admin
from user.models import User
class UserAdmin(admin.ModelAdmin):
list_per_page = 10 # 每页显示和10条数据
display_list = ['username', 'password'] # 指定显示的数据,可以是字段名或者时方法
6 上传图片及分页
6.1 上传图片
新建图片的保存文件夹
在setting.py
文件中配置上传文件保存的位置
MEDIA_ROOT = '路径'
class ImageTest(models.Model):
img = models.ImageField(upload_to='路径')
def upload_image(request):
pic = request.FILE['上传文件的name']
with open(save_path, 'wb') as f:
for content in pic.chunks():
f.write(coontent)
6.2 分页
from user.models import User
from django.core.paginator import Paginator
def index(request):
users = User.objects.all() # 数据查询
paginator = Paginator(users, 10) # 每页按照10条数据进行分页
# paginator.num_page # 总页数
# paginator.range # 返回分页页面的列表
page = paginator.page(x) # 返回x页的数据
# page.number # page的页码数
# page.object_list # page数据的查询集
# page.paginator # 返回Paginator对象
# page.has_previous() # 是否还有前一页
# page.has_next() # 是否含有后一页
# page.previous_next_page_number() # 前一页页码
# page.next_page_number() # 后一页页码