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 状态保持

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')  



8 帮助文档

[1] django admin后台管理 https://docs.djangoproject.com/en/2.2/ref/contrib/admin

[2] Form类 https://www.cnblogs.com/liwenzhou/p/8747872.html

[3] Django-Middleware 应用 http://c.biancheng.net/view/8137.html

posted @ 2020-11-11 11:34  爱编程_喵  阅读(88)  评论(0)    收藏  举报
jQuery火箭图标返回顶部代码

jQuery火箭图标返回顶部代码

滚动滑动条后,查看右下角查看效果。很炫哦!!

适用浏览器:IE8、360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗.