博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【精华】【学以致用】Django精华总结
阅读量:5811 次
发布时间:2019-06-18

本文共 82866 字,大约阅读时间需要 276 分钟。

  hot3.png

简单入门和梳理

1、WEB框架

    MVC

        Model       View       Controller
        数据库   模板文件    业务处理
    MTV
        Model    Template     View
        数据库   模板文件    业务处理
    ############## WEB:MVC、MTV

2、Django

    #安装

    pip3 install django
    
    # 创建Django工程
    django-admin startproject 【工程名称】

        mysite
            - mysite        # 对整个程序进行配置
                - init
                - settings  # 配置文件
                - url       # URL对应关系
                - wsgi      # 遵循WSIG规范,uwsgi + nginx
            - manage.py     # 管理Django程序:
                                - python manage.py
                                - python manage.py startapp xx
                                - python manage.py makemigrations
                                - python manage.py migrate
       
    # 运行Django功能
    python manage.py runserver 127.0.0.1:8001
    # 创建app
    python manage.py startapp cmdb
    python manage.py startapp openstack
    python manage.py startapp xxoo....

    # app目录结构

    app:
        migrations     数据修改表结构
        admin          Django为我们提供的后台管理
        apps           配置当前app
        models         ORM,写指定的类  通过命令可以创建数据库结构
        tests          单元测试
        views          业务代码

    1、配置模板的路径

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',            ],        },    },]

    2、配置静态目录static(    最后一行添加)

STATICFILES_DIRS = (    os.path.join(BASE_DIR, 'static'),)

 

        3、app下views.py

def func(request):    # request.method   GET / POST        # http://127.0.0.1:8009/home?nid=123&name=alex    # request.GET.get('',None)   # 获取请求发来的而数据    # request.POST.get('',None)            # return HttpResponse("字符串")    # return render(request, "HTML模板的路径")    # return redirect('/只能填URL')

    4、模板渲染

            -- {
{ 变量名 }}

def func(request):    return render(request, "index.html", {'current_user': "wangxihao"})
..
{
{current_user}}

        -- For循环

def func(request):    return render(request, "index.html", {'current_user': "w1", 'user_list': ['w1','w2']})
..
{
{current_user}}
    {% for row in user_list %} {% if row == "w1" %}
  • {
    { row }}
  • {% endif %} {% endfor %}

#####索引#####

# viewsdef func(request):    return render(request, "index.html", {'current_user': "alex", 			                  'user_list': ['alex','eric'], 					  'user_dict': {'k1': 'v1', 'k2': 'v2'}})
..
{
{current_user}}
{
{ user_list.1 }}
{
{ user_dict.k1 }}
{
{ user_dict.k2 }}

第二课

    1、Django请求生命周期

        -> URL对应关系(匹配) -> 视图函数 -> 返回用户字符串
        -> URL对应关系(匹配) -> 视图函数 -> 打开一个HTML文件,读取内容

    2、路由系统

  • url(r'^index/', views.index),    
    url(r'^home/', views.Home.as_view()),
  • url(r'^detail-(\d+).html', views.detail),  
  • url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail)

           实战1:

url(r'^detail-(\d+)-(\d+).html', views.detail),def func(request, nid, uid):    passdef func(request, *args):    args = (2,9)def func(request, *args, **kwargs):    args = (2,9)

           实战2:

url(r'^detail-(?P
\d+)-(?P
\d+).html', views.detail)def func(request, nid, uid): pass def funct(request, **kwargs): kwargs = {'nid': 1, 'uid': 3} def func(request, *args, **kwargs): args = (2,9)

 

  • name
    对URL路由关系进行命名, ***** 以后可以根据此名称生成自己想要的URL *****
    url(r'^asdfasdfasdf/', views.index, name='i1'),url(r'^yug/(\d+)/(\d+)/', views.index, name='i2'),url(r'^buy/(?P
    \d+)/(?P
    \d+)/', views.index, name='i3'),
    def func(request, *args, **kwargs):    from django.urls import reverse        url1 = reverse('i1')                              # asdfasdfasdf/    url2 = reverse('i2', args=(1,2,))                 # yug/1/2/    url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) # buy/1/9/
    {% url "i1" %} # asdfasdfasdf/{% url "i2" 1 2 %} # yug/1/2/{% url "i3" pid=1 nid=9 %} # buy/1/9/

    PS:当前的URL----request.path_info

  • 默认值

    # urlsurl(r'^index/', views.index, {'name': 'root'}),		# viewsdef index(request,name):    print(name)    return HttpResponse('OK')

    **这里没有完全弄明白~

    一种传递参数的方式。呵呵

  • 命名空间

    /admin/    include('app01.urls',namespace='m1')/crm/      include('app01.urls',namespace='m2')			app01.urls/index/(?P
    \d+) name = 'n1' # 通过namespace:name,反向生成URLreverser('m1:n1' kwargs={'arg1':11}) # /admin/index/11reverser('m2:n1') # /crm/index# 模板语言下的reverser{% url 'm1:n1' arg1=11 %} # /admin/index/11

    **这里没有完全弄明白~   

    使用reverser的方法,解决调用同一views函数时,路径的区分问题。基本用不到。呵呵
     

    3、视图

        1、获取用户请求数据

            request.body  # 所有内容的原始值
                request.GET
                request.POST
                request.FILES
                request.xxxx.getlist
            request.meta  # 请求头相关的内容
                request.COOKIES
                request.path_info
                request.method

 

        PS:

            GET:获取数据                
            POST:提交数据
            
        2、checkbox等多选的内容
            request.POST.getlist()

        3、上传文件

# 上传文件,form标签做特殊设置obj = request.FILES.get('fafafa')obj.name    //取文件名obj.size    //取文件大小//obj.chunks()  //取文件f = open(obj.name, mode='wb')for item in obj.chunks():    f.write(item)f.close()

  HTML中表单的特殊设置

        4、FBV & CBV
            function base view

def index(request,*args,**kwargs):    if request.method == "POST":        pass    else request.method == "GET":        pass

            class base view

from django.view import Viewclass Home(View):    def get(self,reqeust,*args,**kwargs):        pass

            建议:两者都用

       订制CBV

from django.view import ViewClass Foo(View):    # 每次在执行Foo 方法时,可以自定义,之前和之后的操作    def dispatch(self,request):        print("before")        result = super(Foo,self).dispatch(request,*args,**kwargs)        print("after")        return result    def get(self,request):        print("get get get")        return Httprespone("get OK")    def post(self,request):        print("post post post")        return Httprespone("post OK")

        5、装饰器

            FBV的装饰器

def auth(func):    def inner(reqeust,*args,**kwargs):    v = reqeust.COOKIES.get('username111')        if not v:            return redirect('/login/')        return func(reqeust, *args,**kwargs)    return inner@authdef home(request):    u = request.COOKIES.get("username")    psw = request.COOKIES.get("psw")    return render(reqeust,'index.html',{'current_user': v})

            CBV的装饰器

from django import viewsfrom django.utils.decorators import method_decorator@method_decorator(auth,name='dispatch')    # 同2、给这个class的所有的方法增加装饰器的另一种方法class Order(views.View):# @method_decorator(auth)    # 2、给这个class中所有的方法增加装饰器# def dispatch(self, request, *args, **kwargs):#     return super(Order,self).dispatch(request, *args, **kwargs)# @method_decorator(auth)    # 1、单独给一个方法提供装饰器def get(self,reqeust):    v = reqeust.COOKIES.get('username111')    return render(reqeust,'index.html',{'current_user': v})def post(self,reqeust):    v = reqeust.COOKIES.get('username111')    return render(reqeust,'index.html',{'current_user': v})# 回顾一下,CBV的书写方式。# urls.py# url('/order/',views.order.as_views)

                6、请求的其他信息

# viewsdef index(request):    print(request.environ)     # environ 存放所有的请求信息    # 除了request.environ以外所有的子方法,都是django封装的。    print(request.POST)    print(request.GET)    print(request.METHOD)    print(request.FILE)    for v,k in request.environ.items():        print(v,k)             # 查看environ所有的信息    # 查看访问的客户端信息    print(request.environ['HTTP_USER_AGENT'])

    3、模板

        3.1、模板的继承(母版block)

Document
{% block pir_css %}{% endblock %}
{% block someCode %}{% endblock %} {% block pir_js %}{% endblock %}
{% extends '母版.html' %}
{% block pir_css %}
{% endblock %}{% block someCode %}

block后面的 someCode 要对应母版的名字。

{
{ someCode }}
{% endblock %}{% block pir_js %}{% endblock %}

# urls.pyfrom django.conf.urls import url,from cmdb import viewsurlpatterns = [    url(r'^cmdb/$', views.index1),    url(r'^cmdb/$', views.index2),]# viewsdef index1(request):    return render(request,"子版1.html",{"someCode":"
HELLO WORLD!!
","OTHER":['other1','other2','other3']})def index2(request): return render(request,"子版2.html",{"someCode":"
HELLO PYTHON!!
","OTHER":[111,222,333]})

        3.2、模板的导入

{% extends '母版.html' %}
{% block pir_css %}
{% endblock %}{% block someCode %}

block后面的 someCode 要对应母版的名字。

{
{ someCode }}
{% include 'tag.html '%}{% endblock %}{% block pir_js %}{% endblock %}

{
{ title }}
    {% for x in other %}
  • {
    {x}}
  • {% endfor %}

        3.3、自定义模板

        3.3.1、simple_tag

a. app下创建templatetags目录b. 任意xxoo.py文件c. 创建template对象 registerd.     @register.simple_tag    def func(a1,a2,a3....)        return "asdfasd"e. settings中注册APPf. 顶部 {% load xxoo %}g. {% 函数名 arg1 arg2 %}缺点:    不能作为if条件优点:    参数任意

        3.3.2、filter

a. app下创建templatetags目录b. 任意xxoo.py文件c. 创建template对象 registerd.     @register.filter    def func(a1,a2)        return "asdfasd"e. settings中注册APPf. 顶部 {% load xxoo %}g. {
{ 参数1|函数名:"参数二,参数三" }} {
{ 参数1|函数名:数字 }}缺点: 最多两个参数,不能加空格优点: 能作为if条件

    3.3.3、分页

        1、XSS攻击,默认DJango后台传递不安全。解决办法:
            1.1,前端模板使用

{
{str | safe}}

            1.2、后端使用

from django.utils.safestring import make_safedef index(request):    str = "

haha

" str = make_safe(str) return render(request,"index.html",{"str1":str1})

        2、具体rerr代码

from django.utils.safestring import mark_safeclass Page:    def __init__(self, current_page, data_count, per_page_count=10, pager_num=7):        self.current_page = current_page        self.data_count = data_count        self.per_page_count = per_page_count        self.pager_num = pager_num    @property    def start(self):        return (self.current_page - 1) * self.per_page_count    @property    def end(self):        return self.current_page * self.per_page_count    @property    def total_count(self):        v, y = divmod(self.data_count, self.per_page_count)        if y:            v += 1        return v    def page_str(self, base_url):        page_list = []        if self.total_count < self.pager_num:            start_index = 1            end_index = self.total_count + 1        else:            if self.current_page <= (self.pager_num + 1) / 2:                start_index = 1                end_index = self.pager_num + 1            else:                start_index = self.current_page - (self.pager_num - 1) / 2                end_index = self.current_page + (self.pager_num + 1) / 2                if (self.current_page + (self.pager_num - 1) / 2) > self.total_count:                    end_index = self.total_count + 1                    start_index = self.total_count - self.pager_num + 1        if self.current_page == 1:            prev = '上一页'        else:            prev = '上一页' % (base_url, self.current_page - 1,)        page_list.append(prev)        for i in range(int(start_index), int(end_index)):            if i == self.current_page:                temp = '%s' % (base_url, i, i)            else:                temp = '%s' % (base_url, i, i)            page_list.append(temp)        if self.current_page == self.total_count:            nex = '下一页'        else:            nex = '下一页' % (base_url, self.current_page + 1,)        page_list.append(nex)        jump = """        GO                """ % (base_url,)        page_list.append(jump)        page_str = mark_safe("".join(page_list))        return page_str

        3、具体分页调用方法

from utils import pagination # 导入上面的代码LIST = []               # 模拟数据for i in range(500):    # 模拟数据    LIST.append(i)      # 模拟数据def user_list(request):    current_page = request.GET.get('p', 1)    current_page = int(current_page)    page_obj = pagination.Page(current_page,len(LIST),val)    data = LIST[page_obj.start:page_obj.end]    page_str = page_obj.page_str("/user_list/")    return render(request, 'user_list.html', {'li': data,'page_str': page_str})

模板语言的取值:   

render(    request,    "xxx.html",    {    'obj':1234,    'k1':[1,2,3,4],    'k2':{'name':'www','age':77}    })

  HTML模板的取值:

{obj}

{k1.3}列表

{k2.name}字典

{% for i in k1 %}

{

{i}}

{% endfor %}{% for row in k2,keys %}

{

{row}}

{% endfor %}{% for row in k2.value %}

{

{row}}

{% endfor %}{% for k,v in k2.items %} {% forloop.counter # 正序循环次数的计数器从1开始 %} {% forloop.counter0 # 正序循环次数的计数器从0开始 %} {% forloop.revcounter # 倒叙循环次数的计数器从开始 %} {% forloop.revcounter0 # 倒叙循环次数的计数器从0开始 %} {% forloop.frist # 判断是否是第一次循环 %} {% forloop.last # 判断是否是最后一次循环 %} {% forloop.parentloop# 显示父循环的次数,需要有父层循环 %}

{

{k}}---{
{v}}

{% endfor %}

  4、ORM操作

select * from tb where id > 1# 对应关系models.tb.objects.filter(id__gt=1)models.tb.objects.filter(id=1)models.tb.objects.filter(id__lt=1)

        4.1、创建类

        ----先写类:

from django.db import models# app01_userinfoclass UserInfo(models.Model):    # id列,自增,主键    # 用户名列,字符串类型,指定长度    username = models.CharField(max_length=32)    password = models.CharField(max_length=64)

    ----注册APP(settings.py)

INSTALLED_APPS = [    'django.contrib.admin',    'django.contrib.auth',    'django.contrib.contenttypes',    'django.contrib.sessions',    'django.contrib.messages',    'django.contrib.staticfiles',    'app01',]

    ----执行命令

python manage.py  makemigrationspython manage.py  migrate

   ********** 注意 ***********

        Django默认使用MySQLdb模块链接MySQL
        主动修改为pymysql,在project同名文件夹下的__init__文件中添加如下代码即可:

pip install pymysql
import pymysqlpymysql.install_as_MySQLdb()

        4.2、字段

AutoField(Field)    - int自增列,必须填入参数 primary_key=TrueBigAutoField(AutoField)    - bigint自增列,必须填入参数 primary_key=True    注:当model中如果没有自增列,则自动会创建一个列名为id的列    from django.db import models    class UserInfo(models.Model):        # 自动创建一个列名为id的且为自增的整数列        username = models.CharField(max_length=32)    class Group(models.Model):        # 自定义自增列        nid = models.AutoField(primary_key=True)        name = models.CharField(max_length=32)SmallIntegerField(IntegerField):    - 小整数 -32768 ~ 32767PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)    - 正小整数 0 ~ 32767IntegerField(Field)    - 整数列(有符号的) -2147483648 ~ 2147483647PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)    - 正整数 0 ~ 2147483647BigIntegerField(IntegerField):    - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807BooleanField(Field)    - 布尔值类型NullBooleanField(Field):    - 可以为空的布尔值CharField(Field)    - 字符类型    - 必须提供max_length参数, max_length表示字符长度TextField(Field)    - 文本类型EmailField(CharField):    - 字符串类型,Django Admin以及ModelForm中提供验证机制IPAddressField(Field)    - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制GenericIPAddressField(Field)    - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6    - 参数:        protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"        unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"URLField(CharField)    - 字符串类型,Django Admin以及ModelForm中提供验证 URLSlugField(CharField)    - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)CommaSeparatedIntegerField(CharField)    - 字符串类型,格式必须为逗号分割的数字UUIDField(Field)    - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证FilePathField(Field)    - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能    - 参数:            path,                      文件夹路径            match=None,                正则匹配            recursive=False,           递归下面的文件夹            allow_files=True,          允许文件            allow_folders=False,       允许文件夹FileField(Field)    - 字符串,路径保存在数据库,文件上传到指定目录    - 参数:        upload_to = ""      上传文件的保存路径        storage = None      存储组件,默认django.core.files.storage.FileSystemStorageImageField(FileField)    - 字符串,路径保存在数据库,文件上传到指定目录    - 参数:        upload_to = ""      上传文件的保存路径        storage = None      存储组件,默认django.core.files.storage.FileSystemStorage        width_field=None,   上传图片的高度保存的数据库字段名(字符串)        height_field=None   上传图片的宽度保存的数据库字段名(字符串)DateTimeField(DateField)    - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]DateField(DateTimeCheckMixin, Field)    - 日期格式      YYYY-MM-DDTimeField(DateTimeCheckMixin, Field)    - 时间格式      HH:MM[:ss[.uuuuuu]]DurationField(Field)    - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型FloatField(Field)    - 浮点型DecimalField(Field)    - 10进制小数    - 参数:        max_digits,小数总长度        decimal_places,小数位长度BinaryField(Field)    - 二进制类型
自定义无符号整数字段    class UnsignedIntegerField(models.IntegerField):        def db_type(self, connection):            return 'integer UNSIGNED'    PS: 返回值为字段在数据库中的属性,Django字段默认的值为:        'AutoField': 'integer AUTO_INCREMENT',        'BigAutoField': 'bigint AUTO_INCREMENT',        'BinaryField': 'longblob',        'BooleanField': 'bool',        'CharField': 'varchar(%(max_length)s)',        'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',        'DateField': 'date',        'DateTimeField': 'datetime',        'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',        'DurationField': 'bigint',        'FileField': 'varchar(%(max_length)s)',        'FilePathField': 'varchar(%(max_length)s)',        'FloatField': 'double precision',        'IntegerField': 'integer',        'BigIntegerField': 'bigint',        'IPAddressField': 'char(15)',        'GenericIPAddressField': 'char(39)',        'NullBooleanField': 'bool',        'OneToOneField': 'integer',        'PositiveIntegerField': 'integer UNSIGNED',        'PositiveSmallIntegerField': 'smallint UNSIGNED',        'SlugField': 'varchar(%(max_length)s)',        'SmallIntegerField': 'smallint',        'TextField': 'longtext',        'TimeField': 'time',        'UUIDField': 'char(32)',
# 注意事项    1.触发Model中的验证和错误提示有两种方式:        a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息        b. 使用ModelForm        c. 调用Model对象的 clean_fields 方法,如:            # models.py            class UserInfo(models.Model):                nid = models.AutoField(primary_key=True)                username = models.CharField(max_length=32)                email = models.EmailField(error_messages={'invalid': '格式错了.'})            # views.py            def index(request):                obj = models.UserInfo(username='11234', email='uu')                try:                    print(obj.clean_fields())                except Exception as e:                    print(e)                return HttpResponse('ok')           # Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。    2.Admin中修改错误提示        # admin.py        from django.contrib import admin        from model_club import models        from django import forms        class UserInfoForm(forms.ModelForm):            age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'})            class Meta:                model = models.UserInfo                # fields = ('username',)                fields = "__all__"                exclude = ['title']                labels = { 'name':'Writer', }                help_texts = {'name':'some useful help text.',}                error_messages={ 'name':{'max_length':"this writer name is too long"} }                widgets={'name':Textarea(attrs={'cols':80,'rows':20})}        class UserInfoAdmin(admin.ModelAdmin):            form = UserInfoForm        admin.site.register(models.UserInfo, UserInfoAdmin)

        4.3、字段的参数

null                数据库中字段是否可以为空    db_column           数据库中字段的列名    default             数据库中字段的默认值    primary_key         数据库中字段是否为主键    db_index            数据库中字段是否可以建立索引    unique              数据库中字段是否可以建立唯一索引    unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引    unique_for_month    数据库中字段【月】部分是否可以建立唯一索引    unique_for_year     数据库中字段【年】部分是否可以建立唯一索引    verbose_name        Admin中显示的字段名称    blank               Admin中是否允许用户输入为空    editable            Admin中是否可以编辑    help_text           Admin中该字段的提示信息    choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作                        如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)    error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;                        字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date                        如:{'null': "不能为空.", 'invalid': '格式错误'}    validators          自定义错误验证(列表类型),从而定制想要的验证规则                        from django.core.validators import RegexValidator                        from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\                        MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator                        如:                            test = models.CharField(                                max_length=32,                                error_messages={                                    'c1': '优先错信息1',                                    'c2': '优先错信息2',                                    'c3': '优先错信息3',                                },                                validators=[                                    RegexValidator(regex='root_\d+', message='错误了', code='c1'),                                    RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),                                    EmailValidator(message='又错误了', code='c3'), ]                            )

       元信息

class UserInfo(models.Model):        nid = models.AutoField(primary_key=True)        username = models.CharField(max_length=32)        class Meta:            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名            db_table = "table_name"            # 联合索引            # 遵循最左前缀模式            index_together = [                ("pub_date", "deadline"),            ]            # 联合唯一索引(固定值都搜索时)            unique_together = (("driver", "restaurant"),)            # admin中显示的表名称+s            verbose_name            # verbose_name 不加5            verbose_name_plural

       4.4、操作ORM

# 增models.User.objects.create(name='qianxiaohu',age=18)dic = {'name': 'xx', 'age': 19}models.User.objects.create(**dic)obj = models.User(name='qianxiaohu',age=18)obj.save()
# 删models.User.objects.filter(id=1).delete()
# 改models.User.objects.filter(id__gt=1).update(name='xxx',age=84)dic = {'name': 'xx', 'age': 19}models.User.objects.filter(id__gt=1).update(**dic)obj = models.Tb1.objects.get(id=1)obj.c1 = '111'obj.save()
# 查models.User.objects.filter(id=1,name='root')models.User.objects.filter(id__gt=1,name='root')models.User.objects.filter(id__lt=1)models.User.objects.filter(id__gte=1)models.User.objects.filter(id__lte=1)models.User.objects.filter(id=1,name='root')dic = {'name': 'xx', 'age__gt': 19}models.User.objects.filter(**dic)v1 = models.Business.objects.all()                              # QuerySet ,内部元素都是对象v2 = models.Business.objects.all().values('id','caption')       # QuerySet ,内部元素都是字典v3 = models.Business.objects.all().values_list('id','caption')  # QuerySet ,内部元素都是元组models.Business.objects.get(id=1)               # 获取到的一个对象,如果不存在就报错models.Business.objects.filter(id=1).first()    # 获得对象或者None,不存在也不会报错
# 获取个数models.Tb1.objects.filter(name='seven').count()# 大于,小于models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值models.Tb1.objects.filter(id__gte=1)              # 获取id大于等于1的值models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值models.Tb1.objects.filter(id__lte=10)             # 获取id小于10的值models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值# inmodels.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in# isnullEntry.objects.filter(pub_date__isnull=True)# contains  --类似sql的like操作models.Tb1.objects.filter(name__contains="ven")models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感models.Tb1.objects.exclude(name__icontains="ven")# rangemodels.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and# 其他类似startswith,istartswith, endswith, iendswith,# order bymodels.Tb1.objects.filter(name='seven').order_by('id')    # ascmodels.Tb1.objects.filter(name='seven').order_by('-id')   # desc# group byfrom django.db.models import Count, Min, Max, Summodels.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"# limit 、offsetmodels.Tb1.objects.all()[10:20]# regex正则匹配,iregex 不区分大小写Entry.objects.get(title__regex=r'^(An?|The) +')Entry.objects.get(title__iregex=r'^(an?|the) +')# dateEntry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))# yearEntry.objects.filter(pub_date__year=2005)Entry.objects.filter(pub_date__year__gte=2005)# monthEntry.objects.filter(pub_date__month=12)Entry.objects.filter(pub_date__month__gte=6)# dayEntry.objects.filter(pub_date__day=3)Entry.objects.filter(pub_date__day__gte=3)# week_dayEntry.objects.filter(pub_date__week_day=2)Entry.objects.filter(pub_date__week_day__gte=2)# hourEvent.objects.filter(timestamp__hour=23)Event.objects.filter(time__hour=5)Event.objects.filter(timestamp__hour__gte=12)# minuteEvent.objects.filter(timestamp__minute=29)Event.objects.filter(time__minute=46)Event.objects.filter(timestamp__minute__gte=29)# secondEvent.objects.filter(timestamp__second=31)Event.objects.filter(time__second=2)Event.objects.filter(timestamp__second__gte=31)

 

# 高级操作# extraextra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)   Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))   Entry.objects.extra(where=['headline=%s'], params=['Lennon'])   Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])   Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])# Ffrom django.db.models import Fmodels.Tb1.objects.update(num=F('num')+1)# Q# 方式一:Q(nid__gt=10)Q(nid=8) | Q(nid__gt=10)Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')# 方式二:con = Q()q1 = Q()q1.connector = 'OR'q1.children.append(('id', 1))q1.children.append(('id', 10))q1.children.append(('id', 9))q2 = Q()q2.connector = 'OR'q2.children.append(('c1', 1))q2.children.append(('c1', 10))q2.children.append(('c1', 9))con.add(q1, 'AND')con.add(q2, 'AND')models.Tb1.objects.filter(con)# 执行原生SQLfrom django.db import connection, connectionscursor = connection.cursor()  # cursor = connections['default'].cursor()cursor.execute("""SELECT * from auth_user where id = %s""", [1])row = cursor.fetchone()

 

################################################################### PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET ###################################################################def all(self)    # 获取所有的数据对象def filter(self, *args, **kwargs)    # 条件查询    # 条件可以是:参数,字典,Qdef exclude(self, *args, **kwargs)    # 条件查询    # 条件可以是:参数,字典,Qdef select_related(self, *fields)     性能相关:表之间进行join连表操作,一次性获取关联的数据。     model.tb.objects.all().select_related()     model.tb.objects.all().select_related('外键字段')     model.tb.objects.all().select_related('外键字段__外键字段')def prefetch_related(self, *lookups)    性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。            # 获取所有用户表            # 获取用户类型表where id in (用户表中的查到的所有用户ID)            models.UserInfo.objects.prefetch_related('外键字段')            from django.db.models import Count, Case, When, IntegerField            Article.objects.annotate(                numviews=Count(Case(                    When(readership__what_time__lt=treshold, then=1),                    output_field=CharField(),                ))            )            students = Student.objects.all().annotate(num_excused_absences=models.Sum(                models.Case(                    models.When(absence__type='Excused', then=1),                default=0,                output_field=models.IntegerField()            )))def annotate(self, *args, **kwargs)    # 用于实现聚合group by查询    from django.db.models import Count, Avg, Max, Min, Sum    v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id'))    # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id    v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1)    # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1    v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1)    # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1def distinct(self, *field_names)    # 用于distinct去重    models.UserInfo.objects.values('nid').distinct()    # select distinct nid from userinfo    注:只有在PostgreSQL中才能使用distinct进行去重def order_by(self, *field_names)    # 用于排序    models.UserInfo.objects.all().order_by('-id','age')def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)    # 构造额外的查询条件或者映射,如:子查询    Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])    Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) def reverse(self):    # 倒序    models.UserInfo.objects.all().order_by('-nid').reverse()    # 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序 def defer(self, *fields):    models.UserInfo.objects.defer('username','id')    或    models.UserInfo.objects.filter(...).defer('username','id')    #映射中排除某列数据 def only(self, *fields):    #仅取某个表中的数据     models.UserInfo.objects.only('username','id')     或     models.UserInfo.objects.filter(...).only('username','id') def using(self, alias):     指定使用的数据库,参数为别名(setting中的设置)################################################### PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS ###################################################def raw(self, raw_query, params=None, translations=None, using=None):    # 执行原生SQL    models.UserInfo.objects.raw('select * from userinfo')    # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名    models.UserInfo.objects.raw('select id as nid from 其他表')    # 为原生SQL设置参数    models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,])    # 将获取的到列名转换为指定列名    name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}    Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)    # 指定数据库    models.UserInfo.objects.raw('select * from userinfo', using="default")    ################### 原生SQL ###################    from django.db import connection, connections    cursor = connection.cursor()  # cursor = connections['default'].cursor()    cursor.execute("""SELECT * from auth_user where id = %s""", [1])    row = cursor.fetchone() # fetchall()/fetchmany(..)def values(self, *fields):    # 获取每行数据为字典格式def values_list(self, *fields, **kwargs):    # 获取每行数据为元祖def dates(self, field_name, kind, order='ASC'):    # 根据时间进行某一部分进行去重查找并截取指定内容    # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)    # order只能是:"ASC"  "DESC"    # 并获取转换后的时间        - year : 年-01-01        - month: 年-月-01        - day  : 年-月-日    models.DatePlus.objects.dates('ctime','day','DESC')def datetimes(self, field_name, kind, order='ASC', tzinfo=None):    # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间    # kind只能是 "year", "month", "day", "hour", "minute", "second"    # order只能是:"ASC"  "DESC"    # tzinfo时区对象    models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)    models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))    """    pip3 install pytz    import pytz    pytz.all_timezones    pytz.timezone(‘Asia/Shanghai’)    """def none(self):    # 空QuerySet对象##################################### METHODS THAT DO DATABASE QUERIES #####################################def aggregate(self, *args, **kwargs):   # 聚合函数,获取字典类型聚合结果   from django.db.models import Count, Avg, Max, Min, Sum   result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid'))   ===> {'k': 3, 'n': 4}def count(self):   # 获取个数def get(self, *args, **kwargs):   # 获取单个对象def create(self, **kwargs):   # 创建对象def bulk_create(self, objs, batch_size=None):    # 批量插入    # batch_size表示一次插入的个数    objs = [        models.DDD(name='r11'),        models.DDD(name='r22')    ]    models.DDD.objects.bulk_create(objs, 10)def get_or_create(self, defaults=None, **kwargs):    # 如果存在,则获取,否则,创建    # defaults 指定创建时,其他字段的值    obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2})def update_or_create(self, defaults=None, **kwargs):    # 如果存在,则更新,否则,创建    # defaults 指定创建时或更新时的其他字段    obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})def first(self):   # 获取第一个def last(self):   # 获取最后一个def in_bulk(self, id_list=None):   # 根据主键ID进行查找   id_list = [11,21,31]   models.DDD.objects.in_bulk(id_list)def delete(self):   # 删除def update(self, **kwargs):    # 更新def exists(self):   # 是否有结果

数据库操作--QuerySet中方法:

- QuerySet中的方法:    - 返回QuerySet类型(select_related,prefetch_related)                select_related        # 一次完成参数内的跨表查询,如果需要跨其他表,则再发起一次请求。            users = models.User.objects.all().select_related('ut')            for row in users:                print(row.user,row.pwd,row.ut_id)                print(row.ut.name)                print(row.tu.name) # 再发起一次SQL请求                prefetch_related                        users = models.User.objects.filter(id__gt=30).prefetch_related('ut','tu')            # select * from users where id > 30            # 获取上一步骤中所有的ut_id=[1,2]            # select * from user_type where id in [1,2]            # select * from user_type where id in [1,2]                        for row in users:                print(row.user,row.pwd,row.ut_id)                print(row.ut.name)

多表关系以及参数

ForeignKey(ForeignObject) # ForeignObject(RelatedField)    to,                         # 要进行关联的表名    to_field=None,              # 要关联的表中的字段名称    on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为                                    - models.CASCADE,删除关联数据,与之关联也删除                                    - models.DO_NOTHING,删除关联数据,引发错误IntegrityError                                    - models.PROTECT,删除关联数据,引发错误ProtectedError                                    - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)                                    - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)                                    - models.SET,删除关联数据,                                                  a. 与之关联的值设置为指定值,设置:models.SET(值)                                                  b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)                                                    def func():                                                        return 10                                                    class MyModel(models.Model):                                                        user = models.ForeignKey(                                                            to="User",                                                            to_field="id"                                                            on_delete=models.SET(func),)    related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()    related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')    limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:                                # 如:                                        - limit_choices_to={'nid__gt': 5}                                        - limit_choices_to=lambda : {'nid__gt': 5}                                        from django.db.models import Q                                        - limit_choices_to=Q(nid__gt=10)                                        - limit_choices_to=Q(nid=8) | Q(nid__gt=10)                                        - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')    db_constraint=True          # 是否在数据库中创建外键约束    parent_link=False           # 在Admin中是否显示关联数据OneToOneField(ForeignKey)    to,                         # 要进行关联的表名    to_field=None               # 要关联的表中的字段名称    on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为                                ###### 对于一对一 ######                                # 1. 一对一其实就是 一对多 + 唯一索引                                # 2.当两个类之间有继承关系时,默认会创建一个一对一字段                                # 如下会在A表中额外增加一个c_ptr_id列且唯一:                                        class C(models.Model):                                            nid = models.AutoField(primary_key=True)                                            part = models.CharField(max_length=12)                                        class A(C):                                            id = models.AutoField(primary_key=True)                                            code = models.CharField(max_length=1)ManyToManyField(RelatedField)    to,                         # 要进行关联的表名    related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()    related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')    limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:                                # 如:                                        - limit_choices_to={'nid__gt': 5}                                        - limit_choices_to=lambda : {'nid__gt': 5}                                        from django.db.models import Q                                        - limit_choices_to=Q(nid__gt=10)                                        - limit_choices_to=Q(nid=8) | Q(nid__gt=10)                                        - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')    symmetrical=None,           # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段                                # 做如下操作时,不同的symmetrical会有不同的可选字段                                    models.BB.objects.filter(...)                                    # 可选字段有:code, id, m1                                        class BB(models.Model):                                        code = models.CharField(max_length=12)                                        m1 = models.ManyToManyField('self',symmetrical=True)                                    # 可选字段有: bb, code, id, m1                                        class BB(models.Model):                                        code = models.CharField(max_length=12)                                        m1 = models.ManyToManyField('self',symmetrical=False)    through=None,               # 自定义第三张表时,使用字段用于指定关系表    through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表                                    from django.db import models                                    class Person(models.Model):                                        name = models.CharField(max_length=50)                                    class Group(models.Model):                                        name = models.CharField(max_length=128)                                        members = models.ManyToManyField(                                            Person,                                            through='Membership',                                            through_fields=('group', 'person'),                                        )                                    class Membership(models.Model):                                        group = models.ForeignKey(Group, on_delete=models.CASCADE)                                        person = models.ForeignKey(Person, on_delete=models.CASCADE)                                        inviter = models.ForeignKey(                                            Person,                                            on_delete=models.CASCADE,                                            related_name="membership_invites",                                        )                                        invite_reason = models.CharField(max_length=64)    db_constraint=True,         # 是否在数据库中创建外键约束    db_table=None,              # 默认创建第三张表时,数据库中表的名称
# 外键:class UserType(models.Model):    caption = models.CharField(max_length=32)# id  caption# 1,普通用户# 2,VIP用户# 3, 游客class User(models.Model):    age = models.IntergerFiled()    name = models.CharField(max_length=10)#字符长度    # user_type_id = models.IntergerFiled() # 约束,    user_type = models.ForeignKey("UserType",to_field='id') # 约束,# name age  user_type_id# 张扬  18     3# 张A扬 18     2# 张B扬 18     2#外键:v = models.User.objects.filter(nid__gt=0)v[0].user_type.caption  ---->  通过.进行跨表

        4.5、AJAX

$.ajax({    url: '/host',    type: "POST",    data: {'k1': 123,'k2': "root"},    //data:{'k1':123,'list':[1,2,3,4]},    //traditional:true,    //这个属性表示,可以传递列表    //processData:false,    //JQ上传文件时,设置不做特殊处理。    //contentType:false,    //JQ上传文件时,设置不做特殊处理。    //后台取值的时候使用 request.POST.getlist("list")      //格式,["1","2","3","4"]    success: function(data){        // data是服务器端返回的字符串        var obj = JSON.parse(data);    }})

   建议:永远让服务器端返回一个字典

# views return HttpResponse(json.dumps(字典))

    4.6、一对多 and 正向操作 and 反向操作

def func():    # User类中,on_delete=models.SET(func)的回调函数    return 5class UserType(models.Model):    name = models.CharField(max_length=32)    class User(models.Model):    name = models.CharField(max_length=32)    pwd = models.CharField(max_length=32)    ....         ForiegnKey(to="UserType",to_field='id',on_delete=models.SET(func))# delete from user where id=1# delete from UserType where id=1 # 报错,因为User表中有数据正在使用UserType,所以会报错。# UserType.objects.filter(id=1).delete()    # 在新版django中,不再报错,直接删除,并连带User表中的关联数据一起删除 # 参考model创建表时的,on_delete方法进行设置。# 正向 ---从User表中操作UserType# v = User.objects.all()# for item in v:#     item.user#     item.pwd#     item.ut.name# User.objects.all().values('user','ut__name')# 反向  ---从UserType表中操作User# v = UserType.objects.all()# for item in v:#     item.name#     item.id#     item.user_set.all()    # 如果在foreignKey(related_name=b),则 item.b.all()                             # 如果在foreignKey(related-query_name=a),则 item.a_set.all() # models.UserType.objects.all().values('name','user__pwd')# 如果在foreignKey(related_name=b)# models.UserType.objects.all().values('b')# 如果在foreignKey(related-query_name=a)# models.UserType.objects.all().values('name','a__pwd')

    4.7、创建多对多

            方式一:自定义关系表

class Host(models.Model):    nid = models.AutoField(primary_key=True)    hostname = models.CharField(max_length=32,db_index=True)    ip = models.GenericIPAddressField(protocol="ipv4", db_index=True)    port = models.IntegerField()    b = models.ForeignKey(to="Business", to_field='id')# 10class Application(models.Model):    name = models.CharField(max_length=32)# 2class HostToApp(models.Model):    hobj = models.ForeignKey(to='Host',to_field='nid')    aobj = models.ForeignKey(to='Application',to_field='id')# HostToApp.objects.create(hobj_id=1,aobj_id=2)

            方式二:自动创建关系表

class Host(models.Model):    nid = models.AutoField(primary_key=True)    hostname = models.CharField(max_length=32,db_index=True)    ip = models.GenericIPAddressField(protocol="ipv4",db_index=True)    port = models.IntegerField()    b = models.ForeignKey(to="Business", to_field='id')# 10class Application(models.Model):    name = models.CharField(max_length=32)    r = models.ManyToManyField("Host")    #无法直接对第三张表进行操作obj = Application.objects.get(id=1)obj.name# 第三张表操作obj.r.add(1)obj.r.add(2)obj.r.add(2,3,4)obj.r.add(*[1,2,3,4])obj.r.remove(1)obj.r.remove(2,4)obj.r.remove(*[1,2,3])obj.r.clear()obj.r.set([3,5,7])# 所有相关的主机对象“列表” QuerySetobj.r.all()# 筛选,筛选出主机名为c1的主机obj.r.filter(hostname="c1")

    4.8、数据验证(偏弱)

# 这句话执行了,email就保存了1234156,尽管不合规。models.tb.objects.create(user=name,email="1234156")# 这句话执行了,email就保存了1234156,尽管不合规。obj = models.tb(user=name,email="1234156")obj.save()# 这里就出现了验证功能。obj = models.tb(user=name,email="1234156")obj.full_clean()    # 执行这句的时候,验证正则规则。如果不合规,就报错了。错误类型是ValidationErrorobj.save()# ValidationError  引申一下。# 这里有一个钩子,虽然不知道有什么用。# xx.full_clean()中有一个方法叫做self.clean(),里面是代码是pass。而这个clean就是所谓的钩子。# 在执行正则验证之后,都会再执行一次clean方法。尽管现在是空的,但我们可以做些东西。#models.pyclass UserInfo(models.Model):    name = models.CharField(max_length=32)    email = models.EmailField()    def clean(self):        # 这里有进行了一次数据库操作,当然可以自定义其他操作。        c = UserInfo.objects.filter(name=self.name).count()        if c:            from django.core.exceptions import ValidationError            rasie ValidationError(message="用户名已存在",code="exist")            # 只能是ValidationError错误哦# 尽管验证功能,还是让验证模块去做最好了。所以只是知道一下就好了。

 

5、cookie

    5.1、cookie 是什么?

            cookie,是客户端上的浏览器储存一个文件。字典格式的。浏览器访问时会将本地的cookie发送的服务器。
            接收方式是

request.COOKIESrequest.COOKIES.get("username")request.COOKIES["username"]# 加密传输cookierequest.get_signed_cookie("username", "kangbazi",salt="基于salt加密")

            设置cookie的方式

rep = HttpResponse(...) 或 rep = render(request, ...)rep['name'] = "WXH"    # 给响应头中添加数据(ResponseHeader)rep.set_cookie(key,value,...)rep.set_signed_cookie(key,value,salt='加密盐',...)    参数:        key,              键        value='',         值        max_age=None,     超时时间 -- 参数分钟秒,倒计时        expires=None,     超时时间(datetime格式)        path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问        domain=None,      Cookie生效的域名        secure=False,     https传输        httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

            JS也可以操作cookie

6、session

    6.1、session的原理

            session是保存的在服务器端的键值对
            session是基于cookie的

    6.2、Session配置(缺少cache)

# settings.py# 配置文件中设置默认操作(通用配置):SESSION_COOKIE_NAME = "sessionid"              # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)SESSION_COOKIE_PATH = "/"                	# Session的cookie保存的路径(默认)SESSION_COOKIE_DOMAIN = None                	# Session的cookie保存的域名(默认)ESSION_COOKIE_SECURE = False                	# 是否Https传输cookie(默认)SESSION_COOKIE_HTTPONLY = True                	# 是否Session的cookie只支持http传输(默认)SESSION_COOKIE_AGE = 1209600                    # Session的cookie失效日期(2周)(默认)SESSION_EXPIRE_AT_BROWSER_CLOSE = False		# 是否关闭浏览器使得Session过期(默认)SESSION_SAVE_EVERY_REQUEST = False              # 是否每次请求都保存Session,默认修改之后才保存(默认)

    6.3、session的5种类型。

        6.3.1、数据库(默认)

Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。 a. 配置 settings.py     SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)         SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)   b. 使用     def index(request):        # 获取、设置、删除Session中数据        request.session['k1']        request.session.get('k1',None)        request.session['k1'] = 123        request.session.setdefault('k1',123) # 存在则不设置        del request.session['k1']         # 所有 键、值、键值对        request.session.keys()        request.session.values()        request.session.items()        request.session.iterkeys()        request.session.itervalues()        request.session.iteritems()          # 用户session的随机字符串        request.session.session_key         # 将所有Session失效日期小于当前日期的数据删除        request.session.clear_expired()         # 检查 用户session的随机字符串 在数据库中是否        request.session.exists("session_key")         # 删除当前用户的所有Session数据        request.session.delete("session_key")         request.session.set_expiry(value)            * 如果value是个整数,session会在些秒数后失效。            * 如果value是个datatime或timedelta,session就会在这个时间后失效。            * 如果value是0,用户关闭浏览器session就会失效。            * 如果value是None,session会依赖全局session失效策略。

        6.3.2、缓存

a. 配置 settings.py     SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置      SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名    SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存   b. 使用     同上

        6.3.3、文件

a. 配置 settings.py     SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T      SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名    SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存 b. 使用     同上

        6.3.4、缓存+数据库

数据库用于做持久化,缓存用于提高效率 a. 配置 settings.py     SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎 b. 使用     同上

        6.3.5、加密cookie

a. 配置 settings.py         SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎 b. 使用     同上

       6.4、 Session用户验证

def login(func):    def wrap(request, *args, **kwargs):        # 如果未登陆,跳转到指定页面        if request.path == '/test/':            return redirect('http://www.baidu.com')        return func(request, *args, **kwargs)    return wrap

 

7、CSRF-跨站请求伪造

    7.1、CSRF原理

        7.1.0、盗取Cookie,伪装登录,为所欲为。
        7.1.1、form添加 {% csrf_token %}
        7.1.2、django会在加载HTML时生成一个随机字符串,保存到cookie中。
        7.1.3、在页面POST提交时,同时会把这个随机字符串提交到服务器。或者在cookie中让django获取。
        7.1.4、获取的随机字符串与django本地的随机字符串做比较,来判断是否阻止页面提交。达到防止跨站请求伪造。
    7.2、Form提交(CSRF)

{% csrf_token %}

    7.3、Ajax提交(CSRF)

            CSRF请求头 X-CSRFToken

    
{% csrf_token %}

    7.4、CSRF的全局与个例

# 全局:# 在settings.py 中 注释或者不注释-中间件 django.middleware.csrf.CsrfViewMiddleware# 局部:# 在单独的views中的方法,添加装饰器。from django.views.decorators.csrf import csrf_exempt,csrf_protect    @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。    @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

8、中间件

    中间件,也叫管道。在 setting.py 中的 MIDDLEWARE_CLASSES 声明。

    中间件的作用是,请求触发之后,现在进入中间件,在进入url.py。离开时,最后执行中间件。

    中间件是一个类,继承 middlewareMixin。比如CsrfViewMiddleware(MiddlewareMixin)

    值得一说的是,MiddlewareMixin方法中有两个重要的方法。

    process_requestprocess_response  

class MiddlewareMixin(object):    def __init__(self, get_response=None):        self.get_response = get_response        super(MiddlewareMixin, self).__init__()    def __call__(self, request):        response = None        if hasattr(self, 'process_request'):            response = self.process_request(request)        if not response:            response = self.get_response(request)        if hasattr(self, 'process_response'):            response = self.process_response(request, response)        return response

    如何写一个中间件?

    1、创建一个中间件的类,并继承MiddlewaveMixin

from django.utils.deprecation import MiddlewareMixinclass MiddlewaveRow1(MiddlewareMixin):    # process_request:访问时触发    def process_request(self,request):        print('MiddlewaveRow1--process_reques')    # process_response:离开(返回)时触发    def process_response(self,request,response):        print('MiddlewaveRow1--process_response')        return responseclass MiddlewaveRow2(MiddlewareMixin):    # process_request:访问时触发    def process_request(self,request):        print('MiddlewaveRow2--process_reques')    # process_response:离开(返回)时触发    def process_response(self,request,response):        print('MiddlewaveRow2--process_response')        return response

    2、将创建的中间件加载到中间件池子中。

MIDDLEWARE_CLASSES = [    'django.middleware.security.SecurityMiddleware',    'django.contrib.sessions.middleware.SessionMiddleware',    'django.middleware.common.CommonMiddleware',   # 'django.middleware.csrf.CsrfViewMiddleware',    'django.contrib.auth.middleware.AuthenticationMiddleware',    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',    'django.contrib.messages.middleware.MessageMiddleware',    'django.middleware.clickjacking.XFrameOptionsMiddleware',    'Middlewave_pool.MiddlewavePool.MiddlewaveRow1',    'Middlewave_pool.MiddlewavePool.MiddlewaveRow2',]

    3、随便访问一个页面吧,再回到IDE看控制台输出的信息。

    4、中间件引申一下,如果在中间件process_request方法中,添加return方法。则,直接从当前中间件的process_response方法向出站方向执行。

        不会进入下一个中间件,也不会进入url.py

    5、中间件的另外3种方法:

        process_view(self,request,xx_view,xx_args,xx_kwargs)
        此方法是在所有process_request执行完成后,读取url列表,获取view(不执行)
        注:xx_view 是url指向的view方法。
        注:xx_args 是url指向的view方法的默认参数。        例如,url(r'test/(\d+)',views.test)   ,xx_args就是(\d+)
        注:xx_kwargs 是url指向的view方法的指名参数。    例如,url(r'test/(?P<nid>(\d+))',views.test)   ,xx_kwargs就是{nid:(\d+)}

        process_exception(self,request,excepton)

        此方法默认不执行,只有在views执行报错时在触发。
        注:excepton中存放的就是views的错误信息。

        process_template_response(self,request,response)

        此方法默认不执行,只有在返回时,使用render方法时才会触发。    
        注:然并卵……

    6、中间件的声明周期

   

        补充:

#中间件中可以定义四个方法,分别是:# 第一次进来时,只有request,穿过所有中间层,取得views方法和views参数后,离开。process_request(self,request)# 第二次带着views方法和参数,再走一遍中间件。中间可以处理一些事情了。process_view(self, request, callback, callback_args, callback_kwargs)# 到这里,process_request和process_view不能有return,否则直接跳转到process_response#只有在离开时使用render()方法,才会触发。process_template_response(self,request,response)# 页面报错时,在这里处理错误。process_exception(self, request, exception)# 页面正常返回时,在这里定制需求。process_response(self, request, response)

9、缓存

    Django中提供了5种缓存方式:

    1、开发调试

# 此为开始调试用,实际内部不做任何操作    # 配置:        CACHES = {            'default': {                'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # 引擎                'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)                'OPTIONS':{                    'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)                    'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)                },                'KEY_PREFIX': '',                                             # 缓存key的前缀(默认空)                'VERSION': 1,                                                 # 缓存key的版本(默认1)                'KEY_FUNCTION' 函数名                                          # 生成key的函数(默认函数会生成为:【前缀:版本:key】)            }        }    # 自定义key    def default_key_func(key, key_prefix, version):        """        Default function to generate keys.        Constructs the key used by all other methods. By default it prepends        the `key_prefix'. KEY_FUNCTION can be used to specify an alternate        function with custom key making behavior.        """        return '%s:%s:%s' % (key_prefix, version, key)    def get_key_func(key_func):        """        Function to decide which key function to use.        Defaults to ``default_key_func``.        """        if key_func is not None:            if callable(key_func):                return key_func            else:                return import_string(key_func)        return default_key_func

    2、内存

# 此缓存将内容保存至内存的变量中    # 配置:        CACHES = {            'default': {                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',                'LOCATION': 'unique-snowflake',            }        }    # 注:其他配置同开发调试版本

    3、文件

# 此缓存将内容保存至文件    # 配置:        CACHES = {            'default': {                'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',                'LOCATION': '/var/tmp/django_cache',            }        }    # 注:其他配置同开发调试版本

    4、数据库

# 此缓存将内容保存至数据库    # 配置:        CACHES = {            'default': {                'BACKEND': 'django.core.cache.backends.db.DatabaseCache',                'LOCATION': 'my_cache_table', # 数据库表            }        }    # 注:执行创建表命令 python manage.py createcachetable

    5、Memcache缓存(python-memcached模块)

# 此缓存使用python-memcached模块连接memcache    CACHES = {        'default': {            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',            'LOCATION': '127.0.0.1:11211',        }    }    CACHES = {        'default': {            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',            'LOCATION': 'unix:/tmp/memcached.sock',        }    }       CACHES = {        'default': {            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',            'LOCATION': [                '172.19.26.240:11211',                '172.19.26.242:11211',            ]        }    }

    6、Memcache缓存(pylibmc模块)

# 此缓存使用pylibmc模块连接memcache        CACHES = {        'default': {            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',            'LOCATION': '127.0.0.1:11211',        }    }    CACHES = {        'default': {            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',            'LOCATION': '/tmp/memcached.sock',        }    }       CACHES = {        'default': {            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',            'LOCATION': [                '172.19.26.240:11211',                '172.19.26.242:11211',            ]        }    }

    缓存的应用三种应用:

    1、全站

使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存    MIDDLEWARE = [        'django.middleware.cache.UpdateCacheMiddleware',        # 其他中间件...        'django.middleware.cache.FetchFromCacheMiddleware',    ]    CACHE_MIDDLEWARE_ALIAS = ""    CACHE_MIDDLEWARE_SECONDS = ""    CACHE_MIDDLEWARE_KEY_PREFIX = ""

    2、单独视图

方式一:        from django.views.decorators.cache import cache_page        @cache_page(60 * 15)        def my_view(request):            ...    方式二:        from django.views.decorators.cache import cache_page        urlpatterns = [            url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),        ]

    3、局部模板

a. 引入TemplateTag        {% load cache %}    b. 使用缓存        {% cache 5000 缓存key %}            缓存内容        {% endcache %}

10、内置信号和自定义信号

    内置信号:

Model signals    pre_init                    # django的modal执行其构造方法前,自动触发    post_init                   # django的modal执行其构造方法后,自动触发    pre_save                    # django的modal对象保存前,自动触发    post_save                   # django的modal对象保存后,自动触发    pre_delete                  # django的modal对象删除前,自动触发    post_delete                 # django的modal对象删除后,自动触发    m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发    class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发Management signals    pre_migrate                 # 执行migrate命令前,自动触发    post_migrate                # 执行migrate命令后,自动触发Request/response signals    request_started             # 请求到来前,自动触发    request_finished            # 请求结束后,自动触发    got_request_exception       # 请求异常后,自动触发Test signals    setting_changed             # 使用test测试修改配置文件时,自动触发    template_rendered           # 使用test测试渲染模板时,自动触发Database Wrappers    connection_created          # 创建数据库连接时,自动触发

    对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

from django.core.signals import request_finishedfrom django.core.signals import request_startedfrom django.core.signals import got_request_exceptionfrom django.db.models.signals import class_preparedfrom django.db.models.signals import pre_init, post_initfrom django.db.models.signals import pre_save, post_savefrom django.db.models.signals import pre_delete, post_deletefrom django.db.models.signals import m2m_changedfrom django.db.models.signals import pre_migrate, post_migratefrom django.test.signals import setting_changedfrom django.test.signals import template_renderedfrom django.db.backends.signals import connection_createddef callback(sender, **kwargs):    print("xxoo_callback")    print(sender,kwargs)xxoo.connect(callback)# xxoo指上述导入的内容
from django.core.signals import request_finishedfrom django.dispatch import receiver@receiver(request_finished)def my_callback(sender, **kwargs):    print("Request finished!")

    自定义信号:

        1、定义信号

import django.dispatchpizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

        2、注册信号

def callback(sender, **kwargs):    print("callback")    print(sender,kwargs) pizza_done.connect(callback)

        3、触发信号

from 路径 import pizza_done pizza_done.send(sender='seven',toppings=123, size=456)

11、FORM操作

    Django的Form主要具有一下几大功能:

  • 生成HTML标签
  • 验证用户数据(显示错误信息)
  • HTML Form提交保留上次提交数据
  • 初始化页面显示内容                                                               

    11.1、小试牛刀

            创建form

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fields class MyForm(Form):    user = fields.CharField(        widget=widgets.TextInput(attrs={'id': 'i1', 'class': 'c1'})    )     gender = fields.ChoiceField(        choices=((1, '男'), (2, '女'),),        initial=2,        widget=widgets.RadioSelect    )     city = fields.CharField(        initial=2,        widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))    )     pwd = fields.CharField(        widget=widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)    )

            views

from django.shortcuts import render, redirectfrom .forms import MyForm  def index(request):    if request.method == "GET":        obj = MyForm()        return render(request, 'index.html', {'form': obj})    elif request.method == "POST":        obj = MyForm(request.POST, request.FILES)        if obj.is_valid():            values = obj.clean()            print(values)        else:            errors = obj.errors            print(errors)        return render(request, 'index.html', {'form': obj})    else:        return redirect('http://www.google.com')

            HTML

{

{ form.user }} {
{ form.errors.user.0 }}

{

{ form.gender }} {
{ form.errors.gender.0 }}

{

{ form.city }} {
{ form.errors.city.0 }}

{

{ form.pwd }} {
{ form.errors.pwd.0 }}

        其他form标签

{% csrf_token %} {
{ form.xxoo.label }} {
{ form.xxoo.id_for_label }} {
{ form.xxoo.label_tag }} {
{ form.xxoo.errors }}

{

{ form.user }} {
{ form.user.errors.0 }}

{
{ form.as_p }} {
{ form.as_ul }}
{
{ form.as_table }}

    11.2、Form类

        创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

        Django内置字段如下:

Field    required=True,               是否允许为空    widget=None,                 HTML插件    label=None,                  用于生成Label标签或显示内容    initial=None,                初始值    help_text='',                帮助信息(在标签旁边显示)    error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}    show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)    validators=[],               自定义验证规则    localize=False,              是否支持本地化    disabled=False,              是否可以编辑    label_suffix=None            Label内容后缀  CharField(Field)    max_length=None,             最大长度    min_length=None,             最小长度    strip=True                   是否移除用户输入空白 IntegerField(Field)    max_value=None,              最大值    min_value=None,              最小值 FloatField(IntegerField)    ... DecimalField(IntegerField)    max_value=None,              最大值    min_value=None,              最小值    max_digits=None,             总长度    decimal_places=None,         小数位长度 BaseTemporalField(Field)    input_formats=None          时间格式化    DateField(BaseTemporalField)    格式:2015-09-01TimeField(BaseTemporalField)    格式:11:12DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 DurationField(Field)            时间间隔:%d %H:%M:%S.%f    ... RegexField(CharField)    regex,                      自定制正则表达式    max_length=None,            最大长度    min_length=None,            最小长度    error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'} EmailField(CharField)          ... FileField(Field)    allow_empty_file=False     是否允许空文件 ImageField(FileField)          ...    注:需要PIL模块,pip3 install Pillow    以上两个字典使用时,需要注意两点:        - form表单中 enctype="multipart/form-data"        - view函数中 obj = MyForm(request.POST, request.FILES) URLField(Field)    ...  BooleanField(Field)      ... NullBooleanField(BooleanField)    ... ChoiceField(Field)    ...    choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)    required=True,             是否必填    widget=None,               插件,默认select插件    label=None,                Label内容    initial=None,              初始值    help_text='',              帮助提示  ModelChoiceField(ChoiceField)    ...                        django.forms.models.ModelChoiceField    queryset,                  # 查询数据库中的数据    empty_label="---------",   # 默认空显示内容    to_field_name=None,        # HTML中value的值对应的字段    limit_choices_to=None      # ModelForm中对queryset二次筛选     ModelMultipleChoiceField(ModelChoiceField)    ...                        django.forms.models.ModelMultipleChoiceField       TypedChoiceField(ChoiceField)    coerce = lambda val: val   对选中的值进行一次转换    empty_value= ''            空值的默认值 MultipleChoiceField(ChoiceField)    ... TypedMultipleChoiceField(MultipleChoiceField)    coerce = lambda val: val   对选中的每一个值进行一次转换    empty_value= ''            空值的默认值 ComboField(Field)    fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field)    PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField)    input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']    input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中    path,                      文件夹路径    match=None,                正则匹配    recursive=False,           递归下面的文件夹    allow_files=True,          允许文件    allow_folders=False,       允许文件夹    required=True,    widget=None,    label=None,    initial=None,    help_text='' GenericIPAddressField    protocol='both',           both,ipv4,ipv6支持的IP格式    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用 SlugField(CharField)           数字,字母,下划线,减号(连字符)    ... UUIDField(CharField)           uuid类型    ...

        注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串

        Django内置插件:

# from django.forms import widgets# class MyForm(Form):#     user = fields.CharField(#         widget=widgets.TextInput(attrs={'id': 'i1', 'class': 'c1'})#     )# widgets.xxoo  xxoo就是对应以下HTML标签的生成器。TextInput(Input)                    # type="text"NumberInput(TextInput)              # type="number"EmailInput(TextInput)               # type="email"URLInput(TextInput)                 # type="url"PasswordInput(TextInput)            # type="password"HiddenInput(TextInput)              # type="hidden",隐藏的输入Textarea(Widget)                    # 文本域,textarea标签DateInput(DateTimeBaseInput)        # type="text",带有可选参数format('%Y年%m月%d日,%b缩写月,%B全拼月')DateTimeInput(DateTimeBaseInput)    # type="text",带有可选参数format('%y两位年-%Y-%m-%d %H:%M:%S.%f')TimeInput(DateTimeBaseInput)        # type="text",带有可选参数format('%H:%M:%S.%f')CheckboxInput                       # type="checkbox"Select                              # 下拉菜单,select标签,内涵choices方法NullBooleanSelect                   # 选项为‘Unknown’、‘Yes’ 和‘No’。SelectMultiple                      # 

     11.3、常用选择插件

# 单radio,值为字符串user = fields.CharField(    initial=2,    widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))) # 单radio,值为字符串user = fields.ChoiceField(    choices=((1, '上海'), (2, '北京'),),    initial=2,    widget=widgets.RadioSelect) # 单select,值为字符串user = fields.CharField(    initial=2,    widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))) # 单select,值为字符串user = fields.ChoiceField(    choices=((1, '上海'), (2, '北京'),),    initial=2,    widget=widgets.Select) # 多选select,值为列表user = fields.MultipleChoiceField(    choices=((1,'上海'),(2,'北京'),),    initial=[1,],    widget=widgets.SelectMultiple)  # 单checkboxuser = fields.CharField(    widget=widgets.CheckboxInput())  # 多选checkbox,值为列表user = fields.MultipleChoiceField(    initial=[2, ],    choices=((1, '上海'), (2, '北京'),),    widget=widgets.CheckboxSelectMultiple)

        拓展: 在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

            方式一:

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsfrom django.core.validators import RegexValidator class MyForm(Form):     user = fields.ChoiceField(        # choices=((1, '上海'), (2, '北京'),),        initial=2,        widget=widgets.Select    )    # 因为CharField没有choiecs属性,所以无法user.choiecs    user2 = fields.CharField(widget=widgets.select(choices=[]))     def __init__(self, *args, **kwargs):        super(MyForm,self).__init__(*args, **kwargs)        # self.fields['user'].choices = ((1, '上海'), (2, '北京'),)        # 或        self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id','caption')        # user2的创建方式是CharField , user的创建方式是choiceField        self.fields['user2'].widget.choices = models.XXX.objects.all().value_list('id','caption')

            方式二: 使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现

from django import formsfrom django.forms import fieldsfrom django.forms import widgetsfrom django.forms import models as form_modelfrom django.core.exceptions import ValidationErrorfrom django.core.validators import RegexValidator class FInfo(forms.Form):    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())    # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())# model中的NNewTpye类方法,必须设置__str__(),指定返回的内容。否则authors中存入的是 "NNewType objects"

    11.4、自定义验证规则

        方式一:

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsfrom django.core.validators import RegexValidator class MyForm(Form):    user = fields.CharField(        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],    )

        方式二:

import refrom django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsfrom django.core.exceptions import ValidationError  # 自定义验证规则def mobile_validate(value):    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')    if not mobile_re.match(value):        raise ValidationError('手机号码格式错误')  class PublishForm(Form):      title = fields.CharField(max_length=20,                            min_length=5,                            error_messages={'required': '标题不能为空',                                            'min_length': '标题最少为5个字符',                                            'max_length': '标题最多为20个字符'},                            widget=widgets.TextInput(attrs={'class': "form-control",                                                          'placeholder': '标题5-20个字符'}))      # 使用自定义验证规则    phone = fields.CharField(validators=[mobile_validate, ],                            error_messages={'required': '手机不能为空'},                            widget=widgets.TextInput(attrs={'class': "form-control",                                                          'placeholder': u'手机号码'}))     email = fields.EmailField(required=False,                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},                            widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))

        方式三:

from django import forms    from django.forms import fields    from django.forms import widgets    from django.core.exceptions import ValidationError    from django.core.validators import RegexValidator     class FInfo(forms.Form):        username = fields.CharField(max_length=5,                                    validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], )        email = fields.EmailField()         def clean_username(self):            """            Form中字段中定义的格式匹配完之后,执行此方法进行验证            :return:            """            value = self.cleaned_data['username']            if "666" in value:                raise ValidationError('666已经被玩烂了...', 'invalid')            return value

        方式四: 同时生成多个标签进行验证

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fields from django.core.validators import RegexValidator  ############## 自定义字段 ##############class PhoneField(fields.MultiValueField):    def __init__(self, *args, **kwargs):        # Define one message for all fields.        error_messages = {            'incomplete': 'Enter a country calling code and a phone number.',        }        # Or define a different message for each field.        f = (            fields.CharField(                error_messages={'incomplete': 'Enter a country calling code.'},                validators=[                    RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'),                ],            ),            fields.CharField(                error_messages={'incomplete': 'Enter a phone number.'},                validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')],            ),            fields.CharField(                validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')],                required=False,            ),        )        super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False, *args,                                         **kwargs)     def compress(self, data_list):        """        当用户验证都通过后,该值返回给用户        :param data_list:        :return:        """        return data_list ############## 自定义插件 ##############class SplitPhoneWidget(widgets.MultiWidget):    def __init__(self):        ws = (            widgets.TextInput(),            widgets.TextInput(),            widgets.TextInput(),        )        super(SplitPhoneWidget, self).__init__(ws)     def decompress(self, value):        """        处理初始值,当初始值initial不是列表时,调用该方法        :param value:        :return:        """        if value:            return value.split(',')        return [None, None, None]

    11.5、初始化数据

        在Web应用程序中开发编写功能时,时常用到获取数据库中的数据并将值初始化在HTML中的标签上。

         Form

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsfrom django.core.validators import RegexValidator  class MyForm(Form):    user = fields.CharField()     city = fields.ChoiceField(        choices=((1, '上海'), (2, '北京'),),        widget=widgets.Select    )

         Views

from django.shortcuts import render, redirectfrom .forms import MyForm  def index(request):    if request.method == "GET":        values = {'user': 'root', 'city': 2}        obj = MyForm(values)         return render(request, 'index.html', {'form': obj})    elif request.method == "POST":        return redirect('http://www.google.com')    else:        return redirect('http://www.google.com')

         HTML

{% csrf_token %}

{

{ form.user }} {
{ form.user.errors }}

{

{ form.city }} {
{ form.city.errors }}

    11.6、动态操作select数据

# viewsfrom django.shortcuts import renderfrom app01.forms import UserInfoFormdef index(request):    obj = UserInfoForm()    # 实例化form对象    # obj = UserInfoForm({'字段':"默认值"})    # 初始化Form    # 每个用到usertype的地方,都要写一句这个太麻烦,所以写在构造函数中,一劳永逸。    # obj.fields['user_type'].choices = models.UserType.objects.values_list('id','name')    return render(request, 'index.html', {'obj': obj})
# forms.pyfrom django import formsfrom django.forms import fieldsfrom django.forms import widgetsfrom app01 import modelsclass UserInfoFrom(forms.Form):    user = fields.CharField(        required=False,        widget=widgets.Textarea(attrs={"class": "c1"})    )    pwd = fields.CharField(        max_length=12,        widget=widgets.PasswordInput(attrs={"class": "c1"})    )    user_type = fields.ChoiceField(        # choices=[("0", "游客"), ("1", "普通用户"), ("2", "超级用户")],    # 此为默认方法        choices=models.UserType.objects.values_list("id", "name"),          # 此方法为-数据库读取        # 上面这个方法存在的问题是,当修改数据库后,只有服务器重启后,页面才刷新        # 所以使用构造函数的方法 __init__()        widget=widgets.Select()    )        def __init__(self, *args, **kwargs):        super(UserInfoFrom, self).__init__(*args, **kwargs)        # 每次刷新页面时,会重新读取数据库。        self.fields['UserType'].choices = models.UserType.objects.values_list("id", "name")        # 下面使用的是CharField方法时。        self.fields['UserType'].widgets.choices = models.UserType.objects.values_list("id", "name")

        Form验证----内置钩子

# views.pydef register(request):    from app01.forms import ResisterForm    obj = ResisterForm(request.POST)    if obj.is_valid():        return render(request, 'register.html', {'obj': obj})
# forms.pyclass RegisterForm(forms.Form):    user = fields.CharField()    pwd = fields.CharField()    # form 的第一类钩子,字段的钩子    def clean_user(self):        # 此钩子是单纯只处理user字段的验证,其他字段可单独再次验证。        # 比如,def clean_pwd(self): ... 是单独处理pwd字段。        c = models.UserInfo.objects.filter(name=self.cleaned_data["user"]).count()        if not c:            return self.cleaned_data['user']        else:            from django.core.exceptions import ValidationError            raise ValidationError("用户名已存在", code="xx")    #form 的第二类钩子,整体的钩子    def clean(self):        c = models.UserInfo.objects.filter(name=self.cleaned_data['user'],pwd=self.cleaned_data['pwd']).count()        if c:            # 这里返回的是整体的数据,而不是分字段中的 self.cleaned_data['user']。            return self.cleaned_data        else:            from django.core.exceptions import ValidationError            raise ValidationError("用户名密码错误")    # form 的第三类钩子    def _post_clean(self):        pass

        from错误信息

# views.pydef register(request):    from app01.forms import ResisterForm    from django.core.exceptions import NON_FIELD_ERRORS    obj = ResisterForm(request.POST)    if obj.is_valid():        # obj.cleaned_data        return render(request, 'register.html', {'obj': obj})    else:        # obj.errors        """        {            "__all__":[],        # 整体错误信息            "NON_FIELD_ERRORS":[],        # 整体错误信息的另一个方式            "user":[{"code":"required","message":"xxxxx"}],            "pwd":[{"code":"required","message":"xxxxx"}],        }        """        return render(request, 'register.html', {'obj_error': obj.errors})

        form序列化错误信息

# viewsimport jsonfrom django.shortcuts import HttpResponsefrom django.core.exceptions import ValidationErrorclass JsonCustomEncoder(json.JSONEncoder):    def default(self, o):        if isinstance(o, ValidationError):            return {'code': o.code, 'messages': o.messages}        else:            return json.JSONEncoder.default(self, o)def login(request):    if request.method == "GET":        return render(request, "login.html")    if request.method == "POST":        ret = {'status': True, 'error': None, 'data': None}        obj = LoginForm(request.POST)        if obj.is_valid:            print(obj.cleaned_data)        else:            ret["status"] = False            ret['error'] = obj.errors.as_data()        # json.dumps(str, cls=xx) cls参数是指定每次转码时触发的函数        result = json.dumps(ret, cls=JsonCustomEncoder)        return HttpResponse(result)

        form序列化操作总结---- 万变不离其宗

# views# --------ErrorDict--------# 自定义 encoderimport jsonfrom django.core.exceptions import ValidationErrorclass JsonCustomEncoder(json.JSONEncoder):    def default(self, o):        if isinstance(o, ValidationError):            return {'code': o.code, 'messages': o.messages}        else:            return json.JSONEncoder.default(self, o)# --------QuerySet--------# 第一种方式:serializers 模块from django.core import serializersv = models.tb.objects.all()         # v是一个queryset类型data = serializers.serialize("json", v)     # 进行序列化~~但格式是django指定的格式# 第二种方式:import jsonfrom datetime import datefrom datetime import datetimefrom django.shortcuts import HttpResponseclass JsonCustomEncoder(json.JSONEncoder):    def default(self, field):        if isinstance(field, datetime):            # 还记得strftime方法吗?按照指定格式输出字符串            return field.strftime("%Y-%m-%d %H:%M:%S")        elif isinstance(field, date):            return field.strftime("%Y-%m-%d")        else:            # 如果是其他类型,则按照默认方式转码            return json.JSONEncoder.default(self, field)def index(request):    v = models.tb.objects.values("id", "name", "ctime")     # 这里的ctime 是时间格式的呦~    v = list(v)    v = json.dumps(v, cls=JsonCustomEncoder)    return HttpResponse(v)

12、ModelForm---(不建议使用,应该使用Form和Model分离的方式)

    1、数据库操作

    2、数据验证
    适合小项目。或者,自定制admin

ModelForm    a.  class Meta:            model,                           # 对应Model的            fields=None,                     # 加载Model中指定的字段,全选则fields="__all__"            exclude=None,                    # 加载Model中没有指定的字段            labels=None,                     # 提示信息,类似Model的verbose_name            help_texts=None,                 # 帮助提示信息            widgets=None,                    # 自定义插件 django.forms import widgets as Fwidget |widgets={"指定的fields":fwidgets.Textarea}            error_messages=None,             # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)                                             # 错误信息例子:error_messages = {"name":{"required":"名字不能为空"}}            field_classes=None               # 自定义字段类 (也可以自定义字段)            localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据            如:                数据库中                    2016-12-27 04:10:57                setting中的配置                    TIME_ZONE = 'Asia/Shanghai'                    USE_TZ = True                则显示:                    2016-12-27 12:10:57    b. 验证执行过程        is_valid -> full_clean -> 钩子 -> 整体错误     c. 字典字段验证        def clean_字段名(self):            # 可以抛出异常            # from django.core.exceptions import ValidationError            return "新值"    d. 用于验证        model_form_obj = XXOOModelForm()        model_form_obj.is_valid()        model_form_obj.errors.as_json()        model_form_obj.clean()        model_form_obj.cleaned_data    e. 用于创建        model_form_obj = XXOOModelForm(request.POST)        #### 页面显示,并提交 #####        # 默认保存多对多            obj = form.save(commit=True)        # 不做任何操作,内部定义 save_m2m(用于保存多对多)            obj = form.save(commit=False)            obj.save()      # 保存单表信息            obj.save_m2m()  # 保存关联多对多信息     f. 用于更新和初始化        obj = model.tb.objects.get(id=1)        model_form_obj = XXOOModelForm(request.POST,instance=obj)        ...         PS: 单纯初始化            model_form_obj = XXOOModelForm(initial={...})

 

14、Ajax操作

    1、原生ajax

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/asktao/blog/1558766

你可能感兴趣的文章