• day20 FORM补充(随时更新),F/Q操作,model之多对多,django中间件,缓存,信号


    python-day20

    1、FROM生成select标签的数据应该来源于数据库。

    2、model 操作 F/Q  (组合查询)

    3、model 多对多操作。

    4、中间件 :在请求到达url前先会经过中间件,(比如:中间件进行缓存操作,或者黑名单)

    5、缓存,django提供缓存功能

    6、信号(钩子,保存数据前先执行那些类或者函数)

    7、分页(待上传... ...) 

    cookie:保存在客户端键值对

    session:保存在服务器的一个key


    一、form补充

    class News_Type(models.Model):
        caption = models.CharField(max_length=32)
    #1、国内新闻 2、国际新闻 3、宇宙新闻
    
    
    class New_Text(models.Model):
        title = models.CharField(max_length=32)
        content  = models.CharField(max_length=32)
        newstype = models.ForeignKey(News_Type)
    

    之前我们使用form生成一个select标签是用的自己写在内存中的数据。

    choice = {
      (1,'国内新闻')  
      (2,'国际新闻') 
      (3,'宇宙新闻') 
    }
    
    以后我们就可以从数据库中获取
    choice = News_Type.objects.all().value_list ('id','name')

    实例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>AddData</title>
    </head>
    <body>
        <form action="/add_data/" method="POST">
            <div>
                {{ obj.name }}    <!-- 这些值都是从后端传递过来的,自动生成相应标签,对应着model中数据库表中的字段  -->
            </div>
            <div>
                {{ obj.age }}
            </div>
            <div>
                {{ obj.user_type }}
            </div>
            <input type="submit" value="提交">
        </form>
        <form action="/add_data/" method="POST">
            <div>
                {{ type.caption }}
            </div>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    前端
    class add_Type(forms.Form):
        caption = forms.CharField(required=True, widget=forms.widgets.Input(attrs={"name":"caption","placeholder":"caption"}))
        #widget=forms.widgets.Input(attrs={"name":"caption","placeholder":"caption"} 给标签添加属性
    
    
    class add_valide(forms.Form):
        name = forms.CharField(max_length=12, widget=forms.widgets.Input(attrs={"name":"name","placeholder":"name"}))
        age = forms.IntegerField(widget=forms.widgets.Input(attrs={"name":"age","placeholder":"age"}))
        choise = model.User_Type.objects.all().values_list("id","caption")
        # choise = { 这是内存模式的
        #         (1,'CTO')
        #         (2,'CEO')
        #         (3,'CFO')
        #     }
        user_type = forms.IntegerField(widget=forms.widgets.Select(choices=choise,attrs={"name":"user_type"}))
    
    def add_data(request):
        if request.method == 'POST':
            objPost_type = add_Type(request.POST)            #用户提交的类型数据
            objPost_userinfo = add_valide(request.POST)      #用户提交的用户信息数据
            post_user = objPost_userinfo.is_valid()          #form验证判断
            post_tye = objPost_type.is_valid()               #form验证判断
            if post_user or post_tye:                        #如果这两个判断中有一个是真
                if post_tye:                                 #如果类型为真
                    cap = objPost_type.clean()['caption']               #objPost_type.clean()是获取到用户提交的数值{"caption":"CTO"}
                    model.User_Type.objects.create(caption=cap)         #创建用户类型
                    return render(request, "add_data.html", {"obj": objPost_userinfo, "type": post_tye})
                else:                                                   #用户数据为真
                    user_name = objPost_userinfo.clean()['name']        #获取用户输入的name
                    age = objPost_userinfo.clean()['age']               #获取用户输入的age
                    type = objPost_userinfo.clean()['user_type']        #获取用户输入的用户类型
                    model.UserInfo.objects.create(name=user_name,age=age,user_type_id=type)   #插入数据库user_type_id直接使用到了user_type_id这个虚拟字段
                    return render(request, "add_data.html", {"obj": objPost_userinfo,"type":objPost_type})
        else:    #如果用户是get请求
            objGet = add_valide()          #获取form表单
            typeGet = add_Type()           #获取form表单
            print(model.User_Type.objects.all().values("caption"))
            print(model.UserInfo.objects.all().values("name","age","user_type__caption"))
            return render(request, "add_data.html", {"obj": objGet,"type":typeGet})  #直接把表单传递到前段,前段就生成了相应的标签
    views.py

     这样就实现了后端从数据库中获取,并且form提供创建标签的功能

    但是这么写use_type 的内容不会因为新插入数值而改变,需要重启程序

    class add_valide(forms.Form):
        name = forms.CharField(max_length=12, widget=forms.widgets.Input(attrs={"name":"name","placeholder":"name"}))
        age = forms.IntegerField(widget=forms.widgets.Input(attrs={"name":"age","placeholder":"age"}))
        choise = model.User_Type.objects.all().values_list("id","caption")
        user_type = forms.IntegerField(widget=forms.widgets.Select(choices=choise,attrs={"name":"user_type"}))

    注意:因为 choise = model.User_Type.objects.all().values_list("id","caption") 这一条是class add_valide的静态字段,在类加载之后就不会再变化了,及时数据库中有新值插入,也不会去重新加载。

    所以针对add_valide进行改良

    class add_valide(forms.Form):
        name = forms.CharField(max_length=12, widget=forms.widgets.Input(attrs={"name":"name","placeholder":"name"}))
        age = forms.IntegerField(widget=forms.widgets.Input(attrs={"name":"age","placeholder":"age"}))
        choise = model.User_Type.objects.all().values_list("id","caption")
        user_type = forms.IntegerField(widget=forms.widgets.Select(choices=choise,attrs={"name":"user_type"}))
        def __init__(self,*arg, **kwargs):   #init构造函数的特点就是每次请求来都会
            super(add_valide, self).__init__(*arg, **kwargs)
            self.fields['user_type'].widget.choices = model.User_Type.objects.all().values_list("id","caption")
            #就是让 user_type = forms.IntegerField(widget=forms.widgets.Select(choices 重新赋值,赋值的内容是去数据库中获取
    

     

    请求流程

    else:    #如果用户是get请求
    objGet = add_valide() #获取form表单
    typeGet = add_Type() #获取form表单
    print(model.User_Type.objects.all().values("caption"))
    print(model.UserInfo.objects.all().values("name","age","user_type__caption"))
    return render(request, "add_data.html", {"obj": objGet,"type":typeGet}) #直接把表单传递到前段,前段就生成了相应的标签

    每次请求来都会创建 add_valide()对象,创建对象的时候就会执行构造函数 init中的 

     self.fields['user_type'].widget.choices = model.User_Type.objects.all().values_list("id","caption")


      二、Django数据操作之 F/Q

    1、F 作用:找到某个值让这个值在自身基础上做操作(增加,减少或者字符串拼接)

    需求,找到某一些人把他们的工资加500

    在models中我们要实现这个需求用下面的方法是不成的

    想法没有问题,但是实现不了,实现不了,实现不了
    temp = salary + 500 models.UserINfo.objects.fileter().update(salary=temp)

    在sql语句中:

    update userinfo set salary=salary + 500
    

    所以我们就要用F来实现

    # F 使用查询条件的值
        
        from django.db.models import F
        models.Tb1.objects.update(num=F('num')+1)


    from django.db import connection cursor = connection.cursor() cursor.execute("""SELECT * from tb where name = %s""", ['Lennon']) row = cursor.fetchone()

    F的具体实现:

    models.UserINfo.objects.fileter().update(salary=F('salary')+ 500)

    2、Q作用:构造搜索条件

    目前我们学到的搜索条件是:
    models.IserInfo.objects.filter(id=123,name="alex")
    或者:
    d  = {'id':123,"name":"alex"}
    models.UserInfo.objects.filter(**d) 默认这样的方式就是and搜索
    

    如果想使用or操作或者其他复杂的操作就需要使用Q对象。

    1	CTO
    2 CTO 3 CEO 4 CFO 5 CFO 6 CFO

     想找到id是1或者2或者3的数据

    con = Q()
            q1 = Q()
            q1.connector = 'OR'
            q1.children.append(('id',1))
            q1.children.append(('id',2))
            q1.children.append(('id',3))
            text = model.UserInfo.objects.filter(q1)
            for i in text:
                print(i.id,i.name)
    

     想找到id是1或者2或者3的并且name=CEO的

    con = Q()
            #先找到id的范围
            q1 = Q()
            q1.connector = 'OR'
            q1.children.append(('id',1))
            q1.children.append(('id',2))
            q1.children.append(('id',3))
    
            #在指定name的要找的名字
            q2 = Q()
            q2.connector = "OR"
            q2.children.append(('name',"CEO"))
    
            #把q1和q2再放到一起做一个AND
            con.add(q1,'AND')
            con.add(q2,'AND')
            text = model.UserInfo.objects.filter(q1)
    

    三、models 多对多

    1、创建

    • Django自动创建第三张表:
    class UserInfo(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField(max_length=3)
        user_type = models.ForeignKey(User_Type)
    
    class Dianzan(models.Model):
        num = models.IntegerField(max_length=12)
        U = models.ManyToManyField(UserInfo)         #创建第三张表
    
    • 自己创建第三项表
    class UserInfo(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField(max_length=3)
        user_type = models.ForeignKey(User_Type)
    
    class Dianzan(models.Model):
        num = models.IntegerField(max_length=12)
    
    class D2U(models.Model):
        D_id = models.ForeignKey('Dianzan')
        U_id = models.ForeignKey('UserInfo')
    
    • Django自动创建第三张表的处理:
    class Boy(models.Model):
        name = models.CharField(max_length=12)
        g = models.ManyToManyField("Girl")
    
    
    class Girl(models.Model):
        name = models.CharField(max_length=12)
    表结构
    b1 = model.Boy.objects.get(name="郭德纲")    #获取男孩名字
    g1 = model.Girl.objects.get(name="王钢蛋")   #获取女孩名字
    gs =
    model.Girl.objects.all()
    因为上面表结构中我们在boy表中定义了第三张表的字段,g,所以我们就可以通过这个字段来操作第三种功能表了
    b1.g.add(g1)  #b1中有一个g的字段 这个g字段就代指的第三张表
    
    
    # 添加数据
    正向操作 #b1.g.add(g1) #b1.g.add(*gs) #添加女孩对象的列表增加多条数据
    因为增加到第三张表中的只是两张表的主键,也就是两张表的id,所以我们也可以只使用id作为add的参数,这样做就省去了上面再查询的过程
    b1.g.add(1)
    b1.g.add(*[1,2,3])

    反向操作:
    在女孩字段中隐含着一个boy_set字段
      g1.boy_set.valuse() #反向查询
     
    # 删除数据
    #b1.g.clear()与b1男孩有关系的女孩全部删除 #b1.g.remove(g1) #b1.g.remove(*g1_obj)
    #b1.g.remove(1)
    #b1.g.remove(*[1,2,3])

    # 添加数据(反向操作) #g1.boy_set.add(b1)
    #g1.boy_set.add(*bs)
    #g1.boy_set.add(1)
    #g1.boy_set.add(*[1,2,3]) # 删除数据(反向操作) #g1.boy_set.remove(b1)
    #g1.boy_set.remove(*bs)
    #g1.boy_set.remove(1)
    #g1.boy_set.remove(*[1,2,3])
    #g1.boy_set.clean() #删除所有与g1有关系的男孩 # 获取数据 #b1.g.all() #b1.g.all().filter(id=1) # 获取数据(反向操作隐含着_set字段) #g1.boy_set.all() #g1.boy_set.all().filter(name='郭德纲')
    #all(),conten

    #跨表查询,从girl表中的一个对象,通过关联表查询到boy表中的数据
    #models.Girl.objects.all().valuse('id','name','boy__name')
    models.Girl.objects.filter(name='王钢蛋').values('id','name','boy__name')
    #这样就查询到了王钢蛋的id name 还有和王钢蛋关联的男孩的名字
    更新:django中没有提供更新,所以需要使用原生sql来实现
    from django.db import connection
        # cursor = connection.cursor()
        # cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
        # row = cursor.fetchone()

    四、Django中间件:

    1.中间件存在的位置

    a、MIDDLEWARE_CLASSES 流程:

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

    django的中间件本身就是一个类,所以我们也可以自己定义一个类

    类路径:class1. models.py 
    class M1:
        def process_request(self,request):
            print('我是中间件')

    在setting中添加这个类
    MIDDLEWARE_CLASSES = [
       'class1.models.M1', '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', ]

    此时我们重启系统然后访问页面

    显示:

    我是中间件     <-------- 这个是关键!!
    [01/Oct/2016 16:06:33] "GET /boy_2_girl/ HTTP/1.1" 200 2
    [{'boy__name': '郭德纲', 'name': '林志玲', 'id': 5}]

    与mange.py在同一目录下的文件夹 wupeiqi/middleware下的auth.py文件中的Authentication类

     2.中间件定义的方法名:

    1、process_request(self,request)           #请求时执行的方法
    2、process_response(self,request,response) #返回时执行的方法
      return response               #返回时必须要return response

    3、process_template_response(self,request,response)     #在views.py 的url函数中,返回中如果有render,才会执行这个方法         

    4、process_exception(self, request, exception)                 #url函数中如果出现异常则会执行这个方法,并且执行的顺序是执行url函数前的方法,再执行url函数,
                                                  #如果url函数中有错误,则会执行在返回的函数中先执行后定义的中间件方法中的exception方法

    5、process_view(self, request, callback, callback_args, callback_kwargs) #执行完所有的request后再执行这个方法
    def middle(request):
        print("views")
        obj = HttpResponse("OK")
        return obj  #  return 中有单独定义的redern方法才会触发process_template_response

    以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

    中间件执行的顺序

    MIDDLEWARE_CLASSES = [
        'class1.models.M1',
        'class1.models.M2',
        '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',
    ]
    settings
    class M1:
        def process_request(self,request):
            print("M1.process_request")
    
        def process_response(self,request,response):  #参数是django已经定义好的
            print("M1.process_response")
            return response
    
    
    
    class M2:
        def process_request(self,request):
            print("M2.process_request")
    
        def process_response(self, resqust, response):
            print("M2.process_response")
            return response
    中间件
    def middle(request):
        print("views")
        return HttpResponse("ok")
    url 函数

    访问这个url函数,因为定义了中间件,所以所有的访问会经过中间件,中间件中的request是负责接受请求时执行的,response是返回时执行的

    访问后返回的结果:

    M1.process_request
    M2.process_request
    views
    M2.process_response
    M1.process_response
    

    顺序是先经过所有的resquest,然后执行url函数,最后返回时在执行response

    3、更多方法使用:

    class M1:
        def process_request(self,request):
            print("M1.process_request")
    
        def process_response(self,request,response):
            print("M1.process_response")
            return response
    
        def process_view(self, request, callback, callback_args, callback_kwargs):
            print("M1.process_view")
    
        def process_exception(self, request, exception):
            print("M1.exception ,url函数中出错了")
    
    class M2:
        def process_request(self,request):
            print("M2.process_request")
    
        def process_response(self, resqust, response):
            print("M2.process_response")
            return response
    
        def process_view(self, request, callback, callback_args, callback_kwargs):
            print("M2.process_view")
    
        def process_exception(self, request, exception):
            print("M2.exception ,url函数中出错了")
    更多中间件的使用
    M1.process_request             #先执行request
    M2.process_request    
    
    M1.process_view     #再返回去执行vies   M2.process_view

    #然后就执行url函数,如果出错了就执行exception,没有出错则执行response
    M2.exception ,url函数中出错了 #因为出错了,所以出去的时候先执行M2 M1.exception ,url函数中出错了
    M2.process_response #执行完exception后再返回去执行response M1.process_response

      

    4、不同版本中间件使用的区别:

    在1.10之前就是按照上面的方法去写,但是之后需要在定义中间件的时候做一些改变

    from django.utils import deprecation       #倒入这个类
    class M1(deprecation.MiddlewareMixin):  #继承这个方法
        def process_request(self,request):
            print("M1.process_request")
    
        def process_response(self,request,response):
            print("M1.process_response")
            return response
    
    class M2(deprecation.MiddlewareMixin):
        def process_request(self,request):
            print("M2.process_request")
    
        def process_response(self, resqust, response):
            print("M2.process_response")
            return response    
    新版本django 中间件写法

    5、新版本如果其中一个process_requset中return了,则后面的request都不执行了,然后执行process_request对应类中的process_response方法

    b、原版本的流程:

    这个与新版本不同的地方是如果在process_request中 return了,后面的process_request都不执行了,然后依次执行所有的process_response.


    五、django缓存 

    1、配置

    由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

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

    • 开发调试
    • 内存
    • 文件
    • 数据库
    • Memcache缓存(python-memcached模块)
    • Memcache缓存(pylibmc模块)

     a、开发模式:

    # 此为开始调试用,实际内部不做任何操作
        # 配置:
            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
    

    b、内存

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

    c、文件

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

    d、数据库

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

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

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

    2、应用

    a. 全站使用

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

    b、单独视图缓存

    方式一:
            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)),   #这个单独试图支持分页
            ]
    方式一和方式二实现效果是一样的。

    c、局部视图使用

    第一步. 引入TemplateTag
    
            {% load cache %}
    
    第二步. 使用缓存
    
            {% cache 5000 缓存key %}   #5000的秒, 缓存key就是 放在缓存中的名字
                缓存内容
            {% endcache %}
    

    更多猛戳这里


    六、信号

    Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

    1、Django内置信号

    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内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数,放置位置最好放在project同名目录的__init__.py文件中

    from django.core.signals import request_finished
    from django.core.signals import request_started
    from django.core.signals import got_request_exception
    
    from django.db.models.signals import class_prepared
    from django.db.models.signals import pre_init, post_init
    from django.db.models.signals import pre_save, post_save
    from django.db.models.signals import pre_delete, post_delete
    from django.db.models.signals import m2m_changed
    from django.db.models.signals import pre_migrate, post_migrate
    
    from django.test.signals import setting_changed
    from django.test.signals import template_rendered
    
    from django.db.backends.signals import connection_created
    
    
    def callback(sender, **kwargs):
        print("xxoo_callback")
        print(sender,kwargs)
    
    xxoo.connect(callback)  
    # xxoo指上述导入的内容 如: pre_migrate
    from django.core.signals import request_finished
    from django.dispatch import receiver
    
    @receiver(request_finished)
    def my_callback(sender, **kwargs):
        print("Request finished!")
    

      

    2、自定义信号

    a. 定义信号

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

    b. 注册信号

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

    c. 触发信号

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

    由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。  

    更多内容:猛戳这里  

      


    小知识点:

    以get方式传值:

    url:127.0.0.1:8000/index/?q=123
    

    后台:

    def add_url(request):
        q = request.GET.get("q",None)
        print(q)
        return HttpResponse(q)
    

      

    def middle(request):
    print("views")
    obj = HttpResponse("OK")
    return obj # return 中有单独定义的redern方法才会触发process_template_response
  • 相关阅读:
    Android theme应用主题实现
    CSS_复习
    复习_数字与字符串
    网络编程
    JAVA--多线程
    File类
    c#中new hisase关键字
    内存泄漏、程序崩溃的排除办法
    解决跨线程问题的几种办法
    c#接口
  • 原文地址:https://www.cnblogs.com/python-way/p/5917562.html
Copyright © 2020-2023  润新知