zoukankan      html  css  js  c++  java
  • django 知识点扩展

    一、模型部分

    1 关于ForeignKey

    1.1 级联

    在django2版本以上,外键关联的数据需要设置级联更新

    xxx = models.ForeignKey(关联的表,on_delete=model.CASCADE)
    # 级联操作需要注意,如果是一对一的关联,那没问题应该级联删除
    # 但如果是一对多,删除了一个出版社,就把这个出版社的所有书都删了,显然不合理,因为书和出版社只是逻辑联系,不是真的物理关联
    # 所以通常我们会断开一对多的关联表
     publish = models.ForeignKey(to='Publish',on_delete=models.DO_NOTHING,db_constraint=False)
    # db_constraint=False 表示这个外键只有逻辑关联,没有实质的关联
    # 级联也应当修改
    on_delete = models.DO_NOTHING # 删除出版社的时候,书表什么都不做
    on_delete = models.CASCADE # 级联删除
    on_delete = models.SET_NULL # 前提是这个字段可以为空
    on_delete = models.SET_DEFAULT # 前提是有默认值
    

    1.2 参数

    # to 设置要关联的表
    # to_field 设置要关联表的字段
    # related_name 反向查询的时候替代原来的‘表名_set’
    # db_constraint 是否在数据库中创建外键约束,默认为True
    

    2 关于内部类

    内部类class Meta提供模型的元数据,元数据不属于任何字段的东西,是对整张表的描述

    具体拥有的参数

    • ordering 排序选项

      • ordering = ('pk',)
        # 需要注意排序的根据是一个元组,所以如果只有一个根据就要加逗号,排序如果出现重复就会根据第二个元素的排序依据进行排序
        
    • db_table 数据库表名

      • db_table = '数据库表名'
        # 注意此处修改表名是真实的在数据库中的表名被修改了,所以需要重新进行数据迁移
        
    • verbose_name_plural/verbose_name 单复数名称

      • 这是在admin后台管理的时候显示的名称,复数后缀会在中文后加s通常用中文的话就用单数

    其他相关字段

    class UserInfo(models.Model):
            nid = models.AutoField(primary_key=True)
            username = models.CharField(max_length=32)
    
            class Meta:
                # 设置成虚拟表,通常用于通用表,添加一些每个表必有的字段,让其他表继承
                abstract = True
                # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
                db_table = "table_name"
    
                # 联合索引
                index_together = [
                    ("pub_date", "deadline"),
                ]
    
                # 联合唯一索引
                unique_together = (("driver", "restaurant"),)
                
                ordering = ('name',)
                
                # admin中显示的表名称
                verbose_name='哈哈'
    
                # verbose_name加s
                verbose_name_plural=verbose_name
    
    
    

    二、视图函数部分

    1 关于markdown使用

    import markdown
    
    # 将markdown语法渲染成html样式
        article.body = markdown.markdown(article.body,
            extensions=[
            # 包含 缩写、表格等常用扩展
            'markdown.extensions.extra',
            # 语法高亮扩展
            'markdown.extensions.codehilite',
            ])
    # 这里需要注意,原本的文本格式的文章现在转化成了html代码,如果要展示到前端,就要对数据进行转义
    # 复习:转义的两种方式
    
    1 直接在前端参数后面加safe过滤器
    <p>{{ article.body|safe }}</p>
    
    2 在后端给html代码做标记
    from django.utils.safestring import mark_safe
    res = mark_safe(article.body)
    
    

    2、queryset对象

    2.1 可切片

    用python的切片语法去限制查询的数据条数

    Entry.objects.all()[:5]      # (LIMIT 5)
    Entry.objects.all()[5:10]    # (OFFSET 5 LIMIT 5)
    

    不支持负的索引,切片返回的是一个新的查询集,是由原来的查询集筛选得到的。

    2.2 可迭代

    取出的是每一个数据对象

    2.3 惰性查询

    简单来说就是如果只是把查询结果赋值给了一个变量,而没使用这个变量的话,查询语句是不会执行的,只有真正对数据进行操作了才会回过头来执行查询语句。

    2.4 缓存机制?

    2.5 exists()与iterator()方法

    exists

    # 由于简单的if判断也会把整个数据对象集放入cache中,但是我们不需要判断这么多就可以用到exists
    
    if 查询集.exists():
    	# 相当于只从查询集中拿出一条数据进行判断
    	...
    

    iterator

    # 查询得到的数据集可能会非常大,一次性放入内存就会影响性能,我们可以通过iterator把数据集做成一个迭代器
    # 注意做成迭代器的特点,取完数据后数据需要重新查询,无法回头
    # 每次在内存中只会存在一个数据
    objs = Book.objects.all().iterator()
    

    上面两种方法都是为了防止出现cache,所以他可能会增多了我们对数据库的查询,没有完美的方法只有合适的方法。

    2.6 orm额外方法

    model.Student.object.update_or_create(aa=aa,defaults={'bb=bb'})
    # 拿第一个参数作为查询依据,如果存在则修改,如果不存在则新增
    

    3 extra

    由于orm对mysql的封装程度太高,有些情况下我们需要用一些复杂的查询就可以通过extra来对查询注入新的sql语句

    extra可以指定一个或多个 参数,例如 select, where or tables. 这些参数都不是必须的,但是你至少要使用一个!要注意这些额外的方式对不同的数据库引擎可能存在移植性问题.(因为你在显式的书写SQL语句),除非万不得已,尽量避免这样做

    4.1参数之select

    The select 参数可以让你在 SELECT 从句中添加其他字段信息,它应该是一个字典,存放着属性名到 SQL 从句的映射。

    queryResult=models.Article
               .objects.extra(select={'is_recent': "create_time > '2017-09-05'"})
    

    结果集中每个 Entry 对象都有一个额外的属性is_recent, 它是一个布尔值,表示 Article对象的create_time 是否晚于2017-09-05.

    练习:

    # in sqlite:
        article_obj=models.Article.objects
                  .filter(nid=1)
                  .extra(select={"standard_time":"strftime('%%Y-%%m-%%d',create_time)"})
                  .values("standard_time","nid","title")
        print(article_obj)
        # <QuerySet [{'title': 'MongoDb 入门教程', 'standard_time': '2017-09-03', 'nid': 1}]>
    

    4.2参数之where / tables

    您可以使用where定义显式SQL WHERE子句 - 也许执行非显式连接。您可以使用tables手动将表添加到SQL FROM子句。

    wheretables都接受字符串列表。所有where参数均为“与”任何其他搜索条件。

    举例来讲:

    queryResult=models.Article
               .objects.extra(where=['nid in (1,3) OR title like "py%" ','nid>2'])
    
    extra, 额外查询条件以及相关表,排序
                
                    models.UserInfo.objects.filter(id__gt=1)
                    models.UserInfo.objects.all() 
                    # id name age ut_id
                
                
                    models.UserInfo.objects.extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
                    # a. 映射
                        # select 
                        # select_params=None
                        # select 此处 from 表
                    
                    # b. 条件
                        # where=None
                        # params=None,
                        # select * from 表 where 此处
                    
                    # c. 表
                        # tables
                        # select * from 表,此处
                        
                    # c. 排序
                        # order_by=None
                        # select * from 表 order by 此处
                    
                    
                    models.UserInfo.objects.extra(
                        select={'newid':'select count(1) from app01_usertype where id>%s'},
                        select_params=[1,],
                        where = ['age>%s'],
                        params=[18,],
                        order_by=['-age'],
                        tables=['app01_usertype']
                    )
                    """
                    select 
                        app01_userinfo.id,
                        (select count(1) from app01_usertype where id>1) as newid
                    from app01_userinfo,app01_usertype
                    where 
                        app01_userinfo.age > 18
                    order by 
                        app01_userinfo.age desc
                    """
                    
                    result = models.UserInfo.objects.filter(id__gt=1).extra(
                        where=['app01_userinfo.id < %s'],
                        params=[100,],
                        tables=['app01_usertype'],
                        order_by=['-app01_userinfo.id'],
                        select={'uid':1,'sw':"select count(1) from app01_userinfo"}
                    )
                    print(result.query)
                    # SELECT (1) AS "uid", (select count(1) from app01_userinfo) AS "sw", "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."age", "app01_userinfo"."ut_id" FROM "app01_userinfo" , "app01_usertype" WHERE ("app01_userinfo"."id" > 1 AND (app01_userinfo.id < 100)) ORDER BY ("app01_userinfo".id) DESC
                
    

    三、路由部分

    1 url和path的区别

    django1.x版本用的是url

    基本用法:

    from django.conf.urls import url,include
    # 参数部分是放一个{}内部键值对的key在views函数内要以关键字参数接受
    # 别名用于反向解析
    urlpatterns = [
         url(正则表达式, views视图函数,参数,别名),
    ]
    
    # 有名分组 year = 4位数的数字
    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    # 无名分组
    re_path(r'^articles/([0-9]{4})/$', views.year_archive),
    
    # 路由分发
    path('app01/', include(urls))
    
    # 反向解析的应用场景,当我们视图中或者模版中多次用到了某个url
    # 为了防止这个url后期修改导致所有用到的地方都要改,这里通过一个别名反向解析就行
    # 两种反向解析
    
    # 在视图函数中
    from django.shortcuts import reverse
    url = reverse('tag',args=(1,))
    >>> /mytag_test/1
    # 得到的是url路径,args是拼接在后面的参数
    
    # 在页面中
    {% url "别名" 参数  参数%}
    

    django2.x用的大部分是path,也可以导入url去使用,也有结合两种特性的re_path

    # path的第一个是一个写死的路径,不支持正则
    # 第二个参数是具体的视图函数
    # 也可以反向解析
    # 在1.x版本的分组到2中变成了转换器拼接在url后面
    path('article-create/<int:id>/', views.article_create, name='article_create')
    
    # 内置了5中转化器
    str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
    int,匹配正整数,包含0。
    slug,匹配字母、数字以及横杠、下划线组成的字符串。
    uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
    path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
    

    四、模版部分

    1 xss攻击

    当我们服务端提供用户提交js代码的接口,就容易受到xss攻击,去用一些js代码影响我们的服务器。

    如何解决xss攻击?

    python中用了转义,让被设计者标记安全的语言才能显示到页面,内部原理是,如果用户给了<a href = 'meizitu.com'> 点击</a>这样的标签上传,如果标记安全,那这个字符串就会直接渲染到页面上变成一个标签。

    如果我们没有对其转义,他会原封不动的显示在html页面上

    展示的就是一些特殊字符,比如&gt表示的就是>,所以展示到页面的就是在后端显示的

    五、settings

    1 静态资源暴露

    网站所用的静态文件我们通常都放在static内,比如js,css文件,如果要让前端可以用这些静态文件渲染页面,就需要开放接口,关于网站的静态文件,django已经给我们开放了令牌(功能类似于反向解析),我们只要配置路径即可

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

    而用户上传的静态文件,也需要专门有一个文件夹来接收,通常我们用media做文件夹的名字,也可以修改

    # settings.py
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')  # 用户上传的文件就会保存到该文件夹下
    # media是文件夹的名字,可以自定义,一般使用media作为名字
    

    用户只要上传文件,就会自动创建media目录,会自动在media内创建相应的上传目录

    例如models中,avatar字段

    avatar = models.FileField(upload_to='avatar', default='avatar/default.png')
    

    在上传了头像后,media内会自动创建一个avatar文件夹来存放头像

    当然我们配置了路径只能在服务端使用这个路径,如果前端要访问后端的资源,就必须要开放相应的接口

    在urls配置

    固定写法,复制就能使用

    from django.views.static import serve
    from bbs import settings
    url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})
    

    2 项目修改成中文

    LANGUAGE_CODE = 'zh-hans'
    
    TIME_ZONE = 'Asia/shanghai'
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = False
    
    

    六、RBAC:基于角色的权限控制(django内置的auth体系)

    # RBAC :是基于角色的访问控制(Role-Based Access Control ),公司内部系统
    # django的auth就是内置了一套基于RBAC的权限系统
    
    # django中
    	# 后台的权限控制(公司内部系统,crm,erp,协同平台)
    	user表  #用户表
        permssion表 # 权限表
        group表 # 组别表
        user_groups表是user和group的中间表
        group_permissions表是group和permssion中间表
        user_user_permissions表是user和permission中间表
        # 前台(主站),需要用三大认证
        
    # 用户和组别是多对多
    用户a可以是销售组也可以是开发组
    销售组也可以有多个人
    # 组别和权限是多对多
    销售组的人有销售产品的权限,也有检查产品的权限
    检查产品的权限可能管理组也有
    # 用户和权限
    用户可以有多重权限
    一个权限也可以有多个用户拥有
    

    七、django的缓存

    1 缓存6中配置位置

    1. 开发调试(此模式为开发调试使用,实际上不执行任何操作)

    2. 内存缓存

      CACHES = {
       'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',  # 指定缓存使用的引擎
        'LOCATION': 'unique-snowflake',         # 写在内存中的变量的唯一值 
        'TIMEOUT':300,             # 缓存超时时间(默认为300秒,None表示永不过期)
        'OPTIONS':{
         'MAX_ENTRIES': 300,           # 最大缓存记录的数量(默认300)
         'CULL_FREQUENCY': 3,          # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        }  
       }
      }
      
    3. 文件缓存

    4. 数据库缓存

      CACHES = {
       'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',  # 指定缓存使用的引擎
        'LOCATION': 'cache_table',          # 数据库表    
        'OPTIONS':{
         'MAX_ENTRIES': 300,           # 最大缓存记录的数量(默认300)
         'CULL_FREQUENCY': 3,          # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        }  
       }   
      }
      
    5. Memcache缓存(使用python-memcached模块连接memcache)

    6. Memcache缓存(使用pylibmc模块连接memcache)

    2 缓存应用

    Django提供了不同粒度的缓存,可以缓存某个页面,可以只缓存一个页面的某个部分,甚至可以缓存整个网站.

    2.1 视图中使用缓存

    from django.views.decorators.cache import cache_page
    import time
    from .models import *
    
    @cache_page(15)          #超时时间为15秒
    def index(request):
      t=time.time()      #获取当前时间
      bookList=Book.objects.all()
      return render(request,"index.html",locals())
    
    
    # index.html
    <body>
    <h3>当前时间:-----{{ t }}</h3>
    
    <ul>
        {% for book in bookList %}
           <li>{{ book.name }}--------->{{ book.price }}$</li>
        {% endfor %}
    </ul>
    
    </body>
    # 我们可以看到的效果是15秒内不管前端刷新了几次 t都不会改变
    

    2.2 全局使用缓存

    既然是全站缓存,当然要使用Django中的中间件.

    用户的请求通过中间件,经过一系列的认证等操作,如果请求的内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户

    当返回给用户之前,判断缓存中是否已经存在,如果不存在,则UpdateCacheMiddleware会将缓存保存至Django的缓存之中,以实现全站缓存

    缓存整个站点,是最简单的缓存方法
    
    在 MIDDLEWARE_CLASSES 中加入 “update” 和 “fetch” 中间件
    MIDDLEWARE_CLASSES = (
        ‘django.middleware.cache.UpdateCacheMiddleware’, #第一
        'django.middleware.common.CommonMiddleware',
        ‘django.middleware.cache.FetchFromCacheMiddleware’, #最后
    )
    “update” 必须配置在第一个
    “fetch” 必须配置在最后一个
    # 视图和模版都不需要配置
    

    2.3 局部视图缓存

    # views
    from django.views.decorators.cache import cache_page
    import time
    from .models import *
    def index(request):
         t=time.time()      #获取当前时间
         bookList=Book.objects.all()
         return render(request,"index.html",locals())
    
    # index.html
    {% load cache %}
    {% cache 2 'name' %}
     <h3>缓存:-----:{{ t }}</h3>
    {% endcache %}
    
  • 相关阅读:
    多个tomcat配置,解决冲突问题
    多态-重载和覆载
    静态成员、静态类和枚举
    重复使用类--继承和组合
    建立更可靠的OOP程序-类和成员的访问控制
    用ps画一个Gif的小房子(1)
    在h5页面上添加音乐播放
    使用Object类为实例定义方法和属性
    使用 prototype 定义方法和属性
    使用 this 关键字定义方法和属性
  • 原文地址:https://www.cnblogs.com/hz2lxt/p/13530502.html
Copyright © 2011-2022 走看看