Django
1 Django
1.1 Django特点
-
提供项目工程管理的自动化脚本工具
-
数据库ORM支持
-
模板
-
表单
-
认证权限
-
session机制
-
缓存
-
Admin管理站点
1.2 Django项目搭建
1.2.1 项目创建
$pip install django # 安装包
$django-admin startproject 工程名
--------------------------------
#项目工程目录
settings.py >项目配置文件
urls.py > 项目url配置文件
wsgi.py > Web服务器入口
manage.py > 项目管理文件 控制执行操作
----------------------------------
$python manage.py runserver (ip:port) # 运行程序
1.2.2 应用创建(=Flask蓝图)
$python manage.py startapp 应用名
ps:python manage.py startapp test
---------------------------------
# 应用目录
admin.py > 后台管理站点配置
apps.py > 配置应用信息
migrations > 数据库迁移文件
models.py > 数据模型
test.py > 测试文件
views.py > 逻辑视图处理文件
-----------------------------------
创建完应用需要注册
settings.py 注册应用
INSTALL_APPS = ['test.apps.TestConfig',]
1.2 Django命令
-------------------项目管理-----------------
$django-admin startproject 项目工程名 # 创建Django工程
$python manage.py startapp 应用名 # 创建应用
$python manage.py runserver # 项目工程运行
-------------------数据库迁移-----------------
$python manage.py makemigrations # 生成迁移文件
$python manage.py migrate # 迁移到数据库
-------------------配置文件settings.py-----------------
$python manage.py diffsettings # 查看与默认配置的不同
-------------------admin站点管理-----------------
$python manage.py createsuperuser # 创建admin后台站点用户 优先执行python manage.py migrate 创建用户模型类(djanog自带)
$python manage.py chagepassword 用户名 # 更改密码
2 Django配置信息
#----settings.py
# 配置项 都是大写
SECRET_KEY="" # 密钥配置session使用
DEBUG=True # 项目调试模式
ALLOWED_HOSTS=[] # 允许访问的host
INSTALLED_APPS=[] # 应用注册目录
DATABASES={} # 数据库配置信息
TEMPLATES=[] # 模板引擎 + 模板文件加载目录
STATIC_URL="" # 静态资源加载url
STATICFILES_DIRS = [] # 静态资源存放目录
ROOT_URLCONF = 'django_web.urls' # 路由配置目录
MIDDLEWARE=[] # 中间件 视图运行前后的操作
3 Model
3.1 Model(默认sqlite数据库)
# 定义模型类
-------models.py
from django.db import models
# 书籍信息的模型类
class Book(models.Model):
# 创建字段,字段类型
name = models.CharField(max_length=20, verbose_name='名称')
pub_date = models.DateField(verbose_name='发布日期', null=True)
readcount = models.IntegerField(default=0, verbose_name='阅读量')
commentcount = models.IntegerField(default=0, verbose_name='评论量')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'book' # 数据库表名
verbose_name = '图书' # admin站点中显示的名称
def __str__(self):
"""每个数据对象的显示信息"""
return self.name
# 人物信息的模型类
class People(models.Model):
GENDER_CHOICES = (
(0, 'male'),
(1, 'female')
)
name = models.CharField(max_length=20, verbose_name='名称')
gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
description = models.CharField(max_length=200, null=True, verbose_name='描述信息')
book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'people'
verbose_name = '人物信息'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
-------------------------------------------------------------------------------
3.1 其他数据库(Mysql)配置
# ----项目目录__init__.py
# Django<2.2 $pip install pymysql
import pymysql
pymysql.install_as_MySQLdb()
# Django>2.2 $pip install mysqlclient 即可
# -----settings.py(可主从配置)
DATABASE = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'localhost',
'PORT': 3307,
'USER': 'xx',
'PASSWORD': 'yy',
'NAME': '数据库名',
},
'slave': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'localhost',
'PORT': 3308,
'USER': 'xx',
'PASSWORD': 'yy',
'NAME': '数据库名',
},
}
# 通过加载配置文件加载数据库配置信息
----settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
# 设置读取的配置文件目录
'read_default_file': 'C:/Users/FSH/Desktop/mysql.cnf',
# 设置mysql存储引擎
'init_command': 'SET default_storage_engine=INNODB'
}
},
}
----mysql.cnf
[client]
database = django_web
user = root
password = python
default-character-set =utf8
3.2 数据库迁移
$python manage.py makemigrations # 生成迁移文件
$python manage.py migrate # 数据库迁移
3.3 数据库操作
# 字段类型
AutoField 自动增长的IntegerField 通常不用指定 不指定时Django会自动创建属性名为id的自动增长属性
BooleanField 布尔字段 值为True或False
NullBooleanField 支持Null、True、False三种值
CharField 字符串 参数max_length表示最大字符个数
TextField 大文本字段 一般超过4000个字符时使用
IntegerField 整数
SmallIntegerField 小整数 -32768 ~ 32767
DecimalField 十进制浮点数 参数max_digits表示总位数 参数decimal_places表示小数位数
FloatField 浮点数
DateField 日期 参数auto_now表示每次保存对象时 自动设置该字段为当前时间 用于"最后一次修改"的时间戳 它总是使用当前日期 默认为False
参数auto_now_add表示当对象第一次被创建时自动设置当前时间 用于创建的时间戳 它总是使用当前日期 默认为False
参数auto_now_add和auto_now是相互排斥的 组合将会发生错误
TimeField 时间 参数同DateField
DateTimeField 日期时间 参数同DateField
FileField 上传文件字段
ImageField 继承于FileField 对上传的内容进行校验 确保是有效的图片
# 字段约束
null 如果为True 表示允许为空 默认值是False 存储在数据库表示NULL
blank 如果为True 则该字段允许为空白 默认值是False 存储在数据库表示为空字符串
db_column 字段的名称 如果未指定 则使用属性的名称
db_index 若值为True 则在表中会为此字段创建索引 默认值是False
default 默认值
primary_key 若为True 则该字段会成为模型的主键字段 默认值是False 一般作为AutoField的选项使用
unique 如果为True 这个字段在表中必须有唯一值 默认值是False
# 外键约束等级
CASCADE(级联): 父表数据与子表数据一起删除
PROTECT(保护): 抛出异常 防止父表数据关联的外键数据删除
SET_NULL(空值): 父表的数据被删除 则子表数据设置为空 (前提:字段约束为空)
SET_DEFAULT(默认值): 父表的数据被删除 则子表数据设置为默认值(前提:字段约束有默认值)
SET(): 父表数据删除 调用set()值作为外键的值
DO_NOTHING: 外键关联性取决于数据库外键级别的约束
以上的配置都是django外键级别的 在数据库中的外键级别依旧是RESTRICT
数据库的外键约束等级:
RESTRICT:默认的选项 如果想要删除父表的记录时 而在子表中有关联该父表的记录 则不允许删除父表中的记录
NOACTION:同 RESTRICT效果一样 也是首先先检查外键
CASCADE:父表delete update的时候 子表会delete update关联记录
SET NULL:父表delete update的时候 子表会将关联记录的外键字段所在列设为null 所以注意在设计子表时外键不能设为not null
# 数据库操作(ORM)
# 添加方式一
author = Author(name='',...)
author.save()
# 添加方式二
Author.objects.create(name='',...) # 省略save()操作
# 修改
Author.objects.filter(name='xx').update(name='yy')
# 删除
Author.objects.filter().delete()
# 查询
# 基础查询(单一属性)
Author.objects.get(pk=3) >输出单一对象
Author.objects.all() >输出对象集
Author.objects.filter() >输出条件对象
# 过滤(属性名__运算符)
# 常用运算符
gt:>
gte:>=
lt:<
lte:<=
year:年份
month:月份
--------------------------------------------------------------
Author.objects.filter(条件1, 条件2) == Author.objects.filter(条件1).filter(条件2)
Author.objects.filter(pk__exact=3) > 主键为1的查询集对象
Author.objects.filter(name__contains='xx') > 模糊查询(包含)
Author.objects.filter(name__isnull=True) > 非空查询
Author.objects.filter(id__in=[1, 3]) > id=1 | id=3 数据 -非连续查询
Author.objects.filter(id__range=[1, 3]) > 1<=id<=3 数据 -连续查询
Author.objects.execlude(id=1) > 非id=1 对象 (exclude:排除掉符合条件剩下的数据)
----------------------------------------------------------------
# F&Q(多个属性)
from django.db.models import F, Q
Article.objects.filter(read_num__gte=F('comment_num')*1) # F对象可做算数运算 也可以针对同一模型类对象的不同属性比较
Article.objects.filter(Q(read_num__gt=10), Q(pk__lt=3)) == Article.objects.filter(Q()&Q()) # and 多条件
Article.objects.fiter(Q() | Q()) # or
Article.objects.filter(~Q()) # not
# 聚合函数 aggregate > 输出字典类型数据(默认)
Avg:平均值; Count:总数(返回数字); Max:最大值;Sum:总和; (ps: order_by(-字段)>排序 -:表示降序)
Article.objects.aggregate(Sum('read_num')) > {'read_num__sum': 0}
Article.objects.all().order_by('-read_num') 排序
# 关联查询(一>多 || 多>一)
# 一>多[一对象模型.多对象模型_set]
# 一对应的模型类对象.多对应的模型类名小写_set
author = Author.objects.get(name='')
author.article_set.all() # 作家所有文章
<==>
Article.objects.filter(user__name='') # [一模型类关联属性名__一模型类属性名__运算符]
# 多>一[多模型对象.多模型类中的关系类属性名]
# filter(关联模型类名小写__属性名__条件运算符=值)
article = Article.objects.get(id=1)
article.user # 文章所属作者
<==>
Article.objects.filter(author__id=1)
# 查询集对象(queryset)
# 惰性执行(需要查询才执行 之前只是创建了一个查询集) + 缓存(再次查询相同查询集会读取缓存数据)
3.4 Form表单类
# forms字段约束
# required=True 是否为空
# label='' 生成label标签内容
# initial='' 初始值
# disable=False 是否可以编辑
# error_message=None 错误信息{'errmsg': ''}
# CharField
# max_length 最大长度
# min_length 最小长度
# strip = True 是否一处用户输入空白
# IntergerField
# max_value= 最大值
# min_value= 最小值
# DecimalField(IntegerField)
# max_value=None 最大值
# min_value=None 最小值
# max_digits=None 总长度
# decimal_places=None 小数位长度
# BaseTemporalField(Field)
# input_formats=None 时间格式化
# DateField(BaseTemporalField) 格式:1999-1-1
# TimeField(BaseTemporalField) 格式:22:22
# DateTimeField(BaseTemporalField) 格式:1999-1-1 22:22
# DurationField(Field) 时间间隔:%d %H:%M:%S.%f
# RegexField(CharField)
# regex, 自定正则表达式
# max_length=None, 最大长度
# min_length=None, 最小长度
# error_message=None, 错误信息使用 error_messages={'invalid': ''}
# FileField(Field)
# allow_empty_file=False 是否允许空文件
#--------settings.py
MIDDLEWARE = ['django.middleware.csrf.CsrfViewMiddleware'] # csrf服务开启
#--------templates/form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Form</title>
</head>
<body>
<form action="/test2/" method="post">
{{ csrf_input }}
{{ form }}
<input type="submit" value="submit">
</form>
</body>
</html>
#--------models.py
from django import forms
class TestForm(forms.Form):
name = forms.CharField(label="名称", required=True, max_length=20)
date = forms.DateField(label='日期', required=True)
#--------urls.py
urlpatterns = [
url(r'^test2/$', views.FormTest.as_view(), name='test2'),
]
#--------views.py
class FormTest(View):
def get(self, request):
form = TestForm() # 创建Form实例对象 替换前端模板数据
return render(request, 'form.html', {'form': form})
def post(self, request):
form = TestForm(request.POST)
# 校验表单提交数据合法性
if form.is_valid():
print('表单数据>>>', form.cleaned_data)
return HttpResponse('Register:success')
else:
return HttpResponse('Register:fail')
3.5 ModelAdmin后台可视化(admin)
----app.py
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
verbose_name = 'User应用模块'
----admin.py
# 自定义模型管理类(后台显示的字段)
class AuthorManagement(admin.ModelAdmin):
list_display = ['id', 'name', 'age']
# 输出__str__返回值
# 对于 Foreignkey 类型的字段 显示的是 obj.__str__() 返回的值
# 不支持 ManyToManyField 类型的字段 如果需要展示 可以用自定义方法实现
class ArticleManagement(admin.ModelAdmin):
list_display = ['title', 'read_num', 'user']
# 注册模型类 方便在admin后台查看
admin.site.register(Users) # 只能注册一次
admin.site.register(ClsName)
----models.py
class Author(models.Model):
name = models.CharField(max_length=10, verbose_name='作者姓名')
age = models.SmallIntegerField(verbose_name='作者年龄')
email = models.CharField(max_length=20, unique=True, verbose_name='邮箱地址')
class Meta:
db_table = 'authors'
verbose_name = '作家'
verbose_name_plural = verbose_name
def __str__(self):
return "%s-%d-%s" % (self.name, self.age, self.email)
class Article(models.Model):
title = models.CharField(max_length=20, verbose_name='标题')
read_num = models.SmallIntegerField(verbose_name='阅读量', default=0)
comment_num = models.SmallIntegerField(verbose_name='评论量', default=0)
user = models.ForeignKey(Author, on_delete=models.CASCADE, verbose_name='所属作者')
class Meta:
db_table = 'articles'
verbose_name = '文章' # 后台显示的表名
verbose_name_plural = verbose_name # 避免出现复数s
def __str__(self):
return "%s-%d-%d" % (self.title,
self.read_num,
self.comment_num)
3.6 AbstractUser
# 重写AbstractUser--Django自带的模型类
----models.py
class Users(AbstractUser):
pass
----settings.py
# 指定项目用户模型类
AUTH_USER_MODEL = 'users.Users' # 应用名.模型类名
3.7 自定义管理器
----models.py
class AuthorManager(models.Manager):
"""
自定义管理器类
放置于模型类前
"""
def cout(self):
author = super().all()
return author.count()
def get(self, mid):
author = super().all()
return author.filter(id=mid)
class Author(models.Model):
name = models.CharField(max_length=10, verbose_name='作者姓名')
age = models.SmallIntegerField(verbose_name='作者年龄')
email = models.CharField(max_length=20, unique=True, verbose_name='邮箱地址')
aa = AuthorManager() # 自定义管理器类
class Meta:
db_table = 'authors'
verbose_name = '作家'
verbose_name_plural = verbose_name
def __str__(self):
return "%s-%d-%s" % (self.name, self.age, self.email)
----views.py
class Test(View):
def get(self, request):
"""处理get请求"""
# 获取数据
print(Author.aa.get(2)) # <QuerySet [<Author: bb-2-3172013210@qq.com>]>
print(Author.aa.cout()) # 2
return HttpResponse('Test-get')
----urls.py
urlpatterns = [
url(r'^test/$', views.Test.as_view(), name='test2')
]
4 Views(视图处理请求 返回响应数据)
4.1 路由匹配
----项目工程urls.py
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^', include(('users.urls', 'users'), namespace='users')), # namespace:命名空间 区分不同应用同名url
]
----应用urls.py
from django.conf.urls import url
from users import views
urlpatterns = [
url(r'^test/$', views.Test.as_view(), name='test') # reverse('users:test') 反解析url为/test/
]
name:路由命名 区分不同路由 反解析得到url路径
namespace:命名空间 区分不同应用同名url
路由地址反解析: reverse(namespace:name) or reverse(name)
4.2 类视图
from django.views import View
class Login(View):
def get(self, request):
return HttpResponse('get请求')
def post(self, request):
return HttpResponse('Post请求')
#http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
# 继承自View 配置路由时 使用类视图的 as_view()转换成函数形式注册添加到url
# url(r'^login/$', views.Login.as_view(), name='login')
4.3 HttpRequset
request.scheme str 请求的协议种类 http|https
request.body bytes xml json 二进制文件 非表单类型数据
request.path str 请求url 不包含协议名+域名
request.method str 请求方法
request.POST QueryDict 获取表单类型数据
request.GET QueryDict ?k=v&k2=v2获取查询字符串参数
request.META dict 获取请求头headers数据
request.FILES 获取所有上传文件
request.user 请求的用户对象
request.COOKIES dict 获取cookie数据
--------------------------------------
test/11/22
url(r'^test/(\d+)/(\d+)/$', views.Test.as_view(),) #参数名可以任意
or
url(r'^test/(?P<v1>\d+)/(?P<v2>\d+)/$', views.Test.as_view(),) #参数必须为v1,v2
class Test(View):
def get(requset, v1, v2):
return HttpResponse({'v1': v1, 'v2': v2})
---------------------------------------
4.4 HttpResponse
from django.http import HttpResponse
HttpResponse(content='内容', content_type='数据类型', status='状态码')
----HttpResponse子类
HttpResponsePermanentRedirect 301 (永久性挑战)
HttpResponseRedirect 302 (临时性跳转)
HttpResponseNotModified 304
HttpResponseBadRequest 400
HttpResponseNotFound 404
HttpResponseForbidden 403
HttpResponseNotAllowed 405
HttpResponseGone 410
HttpResponseServerError 500
-----JsonResponse
数据类型:json字符串
response = JsonResponse()
response['Content-Type'] = 'application/json'
4.5 实例
----views.py
class Test(View):
def get(self, request):
"""处理get请求"""
# 获取数据
author = Author.objects.get(pk=1)
url = reverse('users:test2') # 解析路由名为url路径
print(url) # /test/
return HttpResponse('Test-get')
----urls.py
urlpatterns = [
url(r'^test/$', views.Test.as_view(), name='test2')
]
# request:就是本次请求的HttpRequest对象 response 就是响应对象HttpResponse
5 template
5.1 静态资源加载设置
DEBUG=True 静态资源加载
----static文件夹
----settings.py
STATIC_URL = '/static/'
# 配置静态文件加载路径
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
DEBUG=False 静态资源加载
----static文件夹
----urls.py
# DEBUG = False 静态资源路径配置 $python manage.py collectstatic
urlpatterns = [url(r'^static/(?P<path>.*)$', static.serve, {'document_root': settings.STATIC_ROOT}, name='static'),]
----settings.py
STATIC_URL = '/static/'
# 配置静态文件加载路径
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
# DEBUG = False 配置静态资源路径
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
5.2 jinja2设置
#默认模板加载
----settings.py
TEMPLATES = [
{ # 模板引擎
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 模板加载目录
'DIRS': [os.path.join(BASE_DIR, 'templates') ],
'APP_DIRS': True,.....}, ]
#jinja2模板引擎($ pip install jinja2)
----settings.py
TEMPLATES = [
# jinja2模板引擎
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
# 模板加载目录
'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',
],
# 添加Jinja2模板引擎环境
'environment': 'jinja2_env.environment',
},
},
# 默认模板引擎配置
{
'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',
],
},
}
]
----jinja2_env.py
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
env.globals.update({
'static': staticfiles_storage.url,
'url': reverse,
})
return env
5.3 csrf
----settings.py
MIDDLEWARE = [
'django.middleware.csrf.CsrfViewMiddleware', # 默认开启csrf服务
]
# 默认模板引擎
{% csrf_token %}
或者
<intput type='hidden' name='csrfmiddlewaretoken' value={{ csrf_token }}>
# jinja2模板引擎
<form>
{{ csrf_input }}
</form>
6 中间件
6.1 中间件
----settings.py
MIDDLEWARE =[] # 默认中间件加载列表
# 中间件
process_request(self,request)
request:请求对象 与视图中用到的request参数是同一个对象
可返回None or HttpResponse
返回Response对象则不会再执行视图函数
在执行视图函数前调用 调用顺序与中间件注册顺序一致(正序)
process_view(self, request, view_func, view_args, view_kwargs)
request:请求对象 与视图中用到的request参数是同一个对象
view_func:要执行的视图函数(它是实际的函数对象,而不是函数的名称作为字符串)
view_args:url路径中将传递给视图的位置参数的元组
view_kwargs:url路径中将传递给视图的关键值参数的字典
在process_request调用后执行 视图函数调用前执行 调用顺序与注册顺序一致
可以有返回值 None or HttpResponse对象 返回HttpResponse则不再执行视图函数
process_template_response(self,request,response)
request:请求对象 与视图中request参数一致
response:响应对象 与视图中返回的response对象一致
必须返回HttpResponse对象
在process_response前 视图函数后调用 调用顺序与注册顺序相反 且视图函数或者process_template_response返回值必须有render()方法 或者是一个TemplateResponse对象
process_exception(self, request, exception)
request:请求对象 与视图中request参数一致
exception: 视图函数产生异常的exception对象
在视图函数调用异常时调用 调用顺序与注册顺序相反
process_response(self, request, response)
request:请求对象 与视图中用到的request参数是同一个对象
response:响应对象 与视图中返回的response是同一个对象
必须返回HttpResponse对象
在视图函数执行后调用 调用顺序与注册顺序相反(倒序)
# 中间件=请求钩子 完成程序预处理 请求前后预处理等操作
6.2 自定义中间件
#----settings.py
MIDDLEWARE =[ 'users.middleware_init.M1',
'users.middleware_init.M2',]
----users/urls.py
urlpatterns = [
url(r'^test3/$', views.Middleware_Test.as_view(), name='test3'),
]
#----users/views.py
class Middleware_Test(View):
def get(self, request):
print('视图函数执行')
response = HttpResponse('OK')
def render():
print('render函数执行')
return HttpResponse('render')
response.render = render
return response
# # 返回值为templateResponse对象调用process_template_response
# return TemplateResponse(request, 'test.html')
#----users/middleware_init.py($python manage.py startapp users)
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.utils.deprecation import MiddlewareMixin
# 自定义中间件
class M1(MiddlewareMixin):
def process_request(self, request):
"""视图函数调用前执行"""
print('m1-process_request执行')
# return HttpResponse("ok1")
def process_response(self, request, response):
"""视图函数调用后执行 必须有response返回值"""
print('m1-process_response执行')
return response
def process_view(self, request, view_func, view_args, view_kwargs):
"""视图函数调用前执行 在process_request调用后执行"""
print('m1-process_view执行')
print('----------m1-process_view------------')
print('view_func:', view_func)
print('view_args:', view_args)
print('view_kwargs', view_kwargs)
# return HttpResponse('process_view1')
def process_template_response(self, request, response):
"""在视图函数后 process_response前调用"""
print('m1-process_template_response执行')
# response = TemplateResponse(request, 'test.html')
return response
def process_exception(self, request, exception):
"""在视图函数调用异常时调用"""
print('m1-process_exception执行')
print('异常信息exception:', exception)
class M2(MiddlewareMixin):
def process_request(self, request):
print('m2-process_request执行')
# return HttpResponse("ok2")
def process_response(self, request, response):
print('m2-process_response执行')
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print('m2-process_view执行')
print('----------m2-process_view------------')
print('view_func:', view_func)
print('view_args:', view_args)
print('view_kwargs', view_kwargs)
# return HttpResponse('process_view2')
def process_template_response(self, request, response):
print('m2-process_template_response执行')
# response = TemplateResponse(request, 'test.html')
return response
def process_exception(self, request, exception):
print('m2-process_exception执行')
print('异常信息exception:', exception)
6.3 实例
#----settings.py
MIDDLEWARE=['users.middleware_init.M3']
#----users/middleware_init.py
ip_pool = dict() # {'127.0.0.1': [1234343.4524, 3214314.65645, 13431441.5456]}
class M3(MiddlewareMixin):
def process_request(self, request):
"""根据时间次数IP访问受限"""
ip = request.META.get('REMOTE_ADDR') # 获取ip
visit_time = time.time() # 访问时间
if ip not in ip_pool:
ip_pool[ip] = [visit_time]
else:
ip_pool[ip].insert(0, visit_time)
# 访问时长
ip_list = ip_pool[ip]
print(ip_pool)
if len(ip_list) == 1:
return HttpResponse('第一次访问')
last_time = ip_list[0] - ip_list[1]
print('ip:{}, 访问次数:{}, 时间差:{}'.format(ip, len(ip_list), last_time))
# 60s内访问受限判断
while ip_list and last_time > 60:
ip_list.pop()
if len(ip_list) > 3:
return HttpResponse('访问过于频繁(>3)')
print('ip:{}, 访问次数:{}, 时间差:{}'.format(ip, len(ip_list), last_time))
#----users/urls.py
urlpatterns = [
url(r'^test4/$', views.Ip_limit.as_view(), name='test4'),
]
#----users/views.py
class Ip_limit(View):
def get(self, request):
# print(request.META.get('REMOTE_ADDR'))
return HttpResponse('ok')
7 状态保持
7.1 cookie
Django -cookie操作
response = HttpResponse()
response.set_cookie('k', v, max_age='过期时间(s)') # 设置cookie
response.delete_cookie('k') # 删除cookie
request.COOKIES.get('k') # 获取cookie信息
7.2 session
Django-session操作
request.session['key'] = value # 添加session
request.session.get('key') # 获取session值
request.session.clear() # 删除所有session 删除值value=''
request.session.flush() # 清空session数据 删除key:value
del request.session['key'] # 删除指定session数据 key:value
request.session.set_expiry(time) # 设置过期时间(s:秒) time=0 浏览器关闭过期 time=None 默认两周
#----settings.py
SESSION_COOKIE_AGE= time # 全局设置session过期时间
Django-cache存储设置
#----settings.py
# 默认缓存 默认存储在表django_session中(desc: session_key | session_data | expire_data)
SESSION_ENGINE='django.contrib.sessions.backends.db'
# 本地缓存
SESSION_ENGINE='django.contrib.sessions.backends.cache'
# 混合存储(优先i/o内存 后数据库)
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
# Redis($pip install django-redis)
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/0',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'
#----settings.py
MIDDLEWARE =['django.contrib.sessions.middleware.SessionMiddleware',] # 默认开启session服务
#----urls.py
urlpatterns = [
url(r'^test5/$', views.Session_cache.as_view(), name='test5'),
]
#----views.py
class Session_cache(View):
"""使用redis存储session"""
def get(self, request):
request.session['name'] = 'fsh'
request.session['age'] = 23
return HttpResponse('session_set:success')