zoukankan      html  css  js  c++  java
  • Django目录介绍、路由系统、 ORM表的创建、XSS攻击、分页、 CBV & FBV

    Django目录介绍、路由系统、 ORM表的创建

    Django目录介绍
            django-admin startproject mysite  在终端创建目录
            cd mysite
            python manage.py startapp app01    创建一个app 
            
            project
                - app01
                    -migrations  和数据库相关,和modal相关
                    - admin   Django自带后台管理相关配置
                    - modal   写类,根据类创建数据库表
                    - test    单元测试
                    - views   业务处理,业务可以分类
                - app02
                - app03
    
        1. 路由系统(位置参数和形式参数不要不要混用,*args,**kwargs可以接收参数)
            url -> 函数
            
            a. /login/ -> def login        SEO权重不高
            
            b. /add-user/(d+)/  ->  def add_user(request,a1)
               /add-user/(d+)/(d+)/ ->  def add_user(request,a1,a2)    位置参数
            
            c. /add-user/(?P<a1>d+)/  ->  def add_user(request,a1)        形式参数
            
            url(r'^index/', views.index),   访问时必须index/这种形式
            url(r'^index$', views.index),   访问时必须index这种形式
            url(r'^index', views.index),     访问时index开头的任意字符串都可以访问
            url(r'^index/(d+).html', views.index),   访问时必须index/(d+).html开头的这种形式
            url(r'^', views.index)            没有匹配成功,设置默认html
            PS: 
                终止符:
                    ^edit$
                伪静态    提高SEO权重
                    url(r'^edit/(w+).html$', views.edit),
            d. 路由分发
                urls.py中
                导入from django.conf.urls import include
                    url(r'^app01/', include('app01.urls')),
                    
                    先在总路由匹配app路径,然后去该app下urls.py中去匹配路径
                    
                
                app01.urls.py
                    url(r'^index.html$', views.index),
                    
            e. 路由系统之别名反向生成url            
                
                根据名称可以反向生成URL
                1. url(r'^index/', views.index,name="n1)
                在Python代码中,在viws.py中
                def index(request):
                    from django.urls import reverse
                    v = reverse('n1')
                    print(v)    #生成url路径/index/
                    
                    
                 url(r'^index/(d+)/', views.index,name="n1)
                在Python代码中,在viws.py中
                def index(request,a1):
                    from django.urls import reverse
                    v = reverse('n1',args={451})
                    print(v)    #生成url路径/index/451/
                            
                 url(r'^index/(?P<a1>d+)/', views.index,name="n1)
                在Python代码中,在viws.py中
                def index(request,a1):
                    from django.urls import reverse
                    v = reverse('n1',kwargs={'a1':1111})
                    print(v)    #生成url路径/index/1111/
                
                2. 在路由文件中
                    url(r'^login/', views.login,name='m1')
                    在html文件中
                    {% url "m1" %} 提交就可以找到/login/路径
                    
                    在路由文件中
                    url(r'^login/(W)/', views.login,name='m1')
                    url(r'^login/(W).html$', views.login,name='m1')
                    在html文件中
                    {% for i in user_list %}
                        <li>{{ i }}|<a href="{% url "m1" i %}">编辑</a></li>
                    {% endfor %}
                    提交就可以找到/login/i路径
                    提交就可以找到/login/i.html路径
                    
                    
                
        3. ORM操作
            ORM利用pymysql第三方工具连接数据库
            默认:使用SQLlite 数据库
            Http请求:
                url -> 视图(模板+数据)
            步骤:
                1. 创建数据库:在数据库创建70db
                2. 在settings中设置
                    # DATABASES = {
                    #     'default': {
                    #         'ENGINE': 'django.db.backends.sqlite3',
                    #         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
                    #     }
                    # }
    
                    DATABASES = {
                        'default': {
                            'ENGINE': 'django.db.backends.mysql',
                            'NAME':'70db',
                            'USER': 'root',
                            'PASSWORD': '',
                            'HOST': 'localhost',
                            'PORT': 3306,
                            }
                    }
            3. 在项目__init__.py中更换默认连接数据库的方式,MySQLDB(修改django默认连接mySQL方式)
                import pymysql
                pymysql.install_as_MySQLdb()
        
        
            4.在app下的models.py下:创建表
            from django.db import models
            
            class user_group(models.Model):
                title = models.CharField(max_length=32)
    
            class user_info(models.Model):
                id = models.BigAutoField(primary_key=True)   #这一列不写也会自动生成
                username=models.CharField(max_length=32)
                password=models.CharField(max_length=64)
                # age = models.IntegerField(null=True)  #设置可以为空,创建表后插入这一列时可以这么设置
                age = models.IntegerField(default=1)
                #默认生成ug_id,设置可以为空,创建表后插入这一列时可以这么设置
                ug = models.ForeignKey("user_group",null=True)
                
    
            
            5.在配置中注册app
            INSTALLED_APPS = [
                'django.contrib.admin',
                'django.contrib.auth',
                'django.contrib.contenttypes',
                'django.contrib.sessions',
                'django.contrib.messages', 
                'django.contrib.staticfiles',
                'app01'
            ]
            
            6.创建数据表
                命令:
                python manage.py makemigrations
                python manage.py migrate
       
            

     

     ORM表的操作

    ORM操作表:
                创建表
                修改表
                删除表
            操作数据行:
                增删改查
                基于ORM实现组表操作
                #新增
                 models.user_group.objects.create(title="销售部")
                 models.user_info.objects.create(user='root',password='pwd',age=18,ug_id=1)
                 查找
                 group_list = models.user_group.objects.all()
                    models.user_group.objects.all().count()  统计个数              
            group_list
    = models.user_group.objects.filter(id=1) group_list = models.user_group.objects.filter(id__gt=1) #大于 group_list = models.user_group.objects.filter(id__lt=1) #小于 print(group_list) #group_list是QuerySet类型,可以看成列表 group_list QuerySet类型(列表) QuerySet类型[obj,obj,obj] for row in group_list: print(row.id,row.title) models.user_info.objects.all() 删除 models.user_group.objects.filter(id=2).delete() 更新 models.user_group.objects.filter(id=2).update(title='公关部') 基于ORM实现员工表操作 1.增加 models.UserInfo.objects.create(user='root',password='123',age=10,ug_id=1) obj = models.UserGroup.objects.filter(id=1).first() #直接取一个值
                models.UserInfo.objects.create(user='root',password='123',age=10,ug=obj) 2. 删除: models.UserInfo.objects.filter(id=2).delete() 3. 修改: models.UserInfo.objects.filter(id=2).update(title='公关部') 4. 查询: group_list = models.UserInfo.objects.all() group_list获取的是QuerySet,内部元素是UserInfo对象,每一个对象代指一行数据, 对象中如果包含ForeignKey,则代指与其关联表的一行数据 for row in group_list: print(row.user) print(row.age) print(row.ug_id) # 用户信息关联的部门ID print(row.ug.title) # 用户信息关联的部门名称

    获取QuerySet(查询集)

    # 获取QuerySet(查询集)
                1.正向操作、反向操作(连表查询)
                     QuerySet[obj,obj,obj]
                     result = models.UserInfo.objects.all()
                     for obj in result:
                         print(obj.name,obj.age,obj.ut_id,obj.ut.title)
    
              正向操作
    UserInfo,ut是FK字段
    - PS: 一个用户只有一个用户类型 obj = models.UserInfo.objects.all().first() print(obj.name,obj.age,obj.ut.title)           反向操作
    UserType, 表名小写_set.all()
    - PS: 一个用户类型下可以有很多用户 obj = models.UserType.objects.all().first() print('用户类型',obj.id,obj.title) for row in obj.userinfo_set.all(): print(row.name,row.age) result = models.UserType.objects.all() for item in result: print(item.title,item.userinfo_set.filter(name='xx'))
    2.数据获取多个数据时 1.列表查询集 [obj,obj,obj,] models.UserInfo.objects.all() models.UserInfo.objects.filter(id__gt=1) result = models.UserInfo.objects.all() for item in result: print(item.name,item.ut.title)           反向跨表:
              1. 小写的表名_set
                 obj = UserGroup.objects.all().first()
                 result = obj.userinfo_set.all() [userinfo对象,userinfo对象,]
              
             
              
    2.字典查询集 [{id:1,name:fd},{id:1,name:fd},{id:1,name:fd},] models.UserInfo.objects.all().values('id','name') models.UserInfo.objects.filter(id__gt=1).values('id','name') 无法跨表 result = models.UserInfo.objects.all().values('id','name') for item in result: print(item['id'],item['name']) 字典查询集正向跨表 __ result = models.UserInfo.objects.all().values('id','name',"ut__title") for item in result: print(item['id'],item['name'],item['ut__title'])           反向跨表:
              2. 小写的表名
                 v = UserGroup.objects.values('id','title')         
                 v = UserGroup.objects.values('id','title','小写的表名称')         
                 v = UserGroup.objects.values('id','title','小写的表名称__age') 

              
    3.元组查询集 [(1,df),(2,'df')] models.UserInfo.objects.all().values_list('id','name') models.UserInfo.objects.filter(id__gt=1).values_list('id','name') 无法跨表 result = models.UserInfo.objects.all().values_list('id','name') for item in result: print(item[0],item[1]) 元组查询集正向跨表 __ result = models.UserInfo.objects.all().values_list('id','name',"ut__title") for item in result: print(item[0],item[1],item[2])
              反向跨表:
              3. 小写的表名
                v = UserGroup.objects.values_list('id','title')         
                v = UserGroup.objects.values_list('id','title','小写的表名称')         
                v = UserGroup.objects.values_list('id','title','小写的表名称__age') 


    select_related、prefetch_related连表查询

    select_related()主要针一对一和多对一关系进行优化,使用SQLJOIN语句进行优化

    prefetch_related()对于多对多字段和一对多字段进行优化

    参考:http://blog.csdn.net/secretx/article/details/43964607

    select_related: 查询主动做连表,连表查询速度慢(适用外键对应的表数据量少时使用)
    q = models.UserInfo.objects.all().select_related('ut','gp')
    # select * from userinfo
    # select * from userinfo inner join usertype on ...
    for row in q:
        print(row.name,row.ut.title)
    
    prefetch_related: 不做连表,做多次查询(使用外键对应的表数据量大,数据频繁查询时使用)
    q = models.UserInfo.objects.all().prefetch_related('ut')
    # select * from userinfo;
    # Django内部:ut_id = [2,4]
    # select * from usertype where id in [2,4]
    for row in q:
        print(row.id,row.ut.title)

    related_query_name和related_name的操作:

    class Boy(models.Model):
        name=models.CharField(max_length=32)
        bpwd = models.IntegerField()
    class Girl(models.Model):
        nick = models.CharField(max_length=32)
        gpwd = models.IntegerField()
    class Love(models.Model):
        b=models.ForeignKey('Boy')
        g=models.ForeignKey('Girl')
        #可以如上这么写,会自动关联表的自增id,也可以指定表和关联id,如下:
        #b = models.ForeignKey(to='Boy',to_field='id')
        #g = models.ForeignKey(to='Girl',to_field='id')
    外键的两种写法
    class UserInfo(models.Model):
        nickname = models.CharField(max_length=32)
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
        gender_choices = (
            (1,''),
            (2,''),
        )
        gender = models.IntegerField(choices=gender_choices)        
    class U2U(models.Model):
        #g = models.ForeignKey('UserInfo',related_query_name='boys')
        #b = models.ForeignKey('UserInfo',related_query_name='girls')
        g = models.ForeignKey('UserInfo',related_name='boys')
        b = models.ForeignKey('UserInfo',related_name='girls')    
        
    外键的操作:
    related_query_name
    obj对象男.girls_set.all()
    obj对象女.boys_set.all()
    related_name
    obj对象男.girls.all()
    obj对象女.boys.all()        
    def test(request):
        #两种创建数据的方式:
        models.U2U.objects.create(b_id=2,g_id=6)
        models.U2U.objects.create(b_id=1,g_id=6)            
    
        boy = models.UserInfo.objects.filter(gender=1,id=2).first()
        girl = models.UserInfo.objects.filter(gender=2,id=6).first()
        models.U2U.objects.create(b=boy,g=girl)
        #创建数据时可以放对象    
        
    外键的操作举例:
    UserInfo对象
    xz = models.UserInfo.objects.filter(id=1).first()
    # 和徐峥有关系的所有信息:U2U列表[U2U对象,2U对象,2U对象,]
    result = xz.girls.all()
    for u in result:
        # U2U对象
        print(u.g.nickname)
    同一个表两个外键

    v.query   查询原生sql语句
    一对一操作的正反向:

     # obj = models.Blog.objects.filter(site=site).first()
        # print(obj.user.nickname)   
        # obj = models.UserInfo.objects.filter(username='sw').first()
        # print(obj.blog.site)        onetoone 反向操作时
    OneToOne操作

    多对多操作:有外键的情况查询操作

    class Boy(models.Model):
        name = models.CharField(max_length=32)
    
    
    class Girl(models.Model):
        nick = models.CharField(max_length=32)
    
    class Love(models.Model):
        b = models.ForeignKey('Boy')
        g = models.ForeignKey('Girl')
        class Meta:            #联合唯一索引
        unique_together = [
            ('b','g'),
        ]
    1. 和方少伟有关系的姑娘
    obj = models.Boy.objects.filter(name='方少伟').first()
    love_list = obj.love_set.all()
    for row in love_list:
        print(row.g.nick)
    
    
    love_list = models.Love.objects.filter(b__name='方少伟')
    for row in love_list:
        print(row.g.nick)
    
    连表操作:
    love_list = models.Love.objects.filter(b__name='方少伟').values('g__nick')
    for item in love_list:
        print(item['g__nick'])
    
    连表操作:
    love_list = models.Love.objects.filter(b__name='方少伟').select_related('g')
    for obj in love_list:
        print(obj.g.nick)
    连表操作

     多对多操作:ManyToManyField、杂交、自定义关系表

    1. ManyToManyField
        class Boy(models.Model):
            name = models.CharField(max_length=32)
            m = models.ManyToManyField('Girl')
            #django内置方式这一行会生成第三张关系表,即app01_boy_m,只能生成三列,如果有多行信息,自己写在第三张表
            #m = models.ManyToManyField('Girl',through="Love",through_fields=('b','g',))
            #杂交,如果这样写就只生成LOVE表
    
        class Girl(models.Model):
            nick = models.CharField(max_length=32)                
            
        #自定义关系表    
        #class Love(models.Model):
        #    b = models.ForeignKey('Boy')
        #    g = models.ForeignKey('Girl')
        #    class Meta:            #联合唯一索引
        #    unique_together = [
        #        ('b','g'),
        #    ]
            
            
            增加:
            obj = models.Boy.objects.filter(name='方少伟').first()
            print(obj.id,obj.name)
            obj.m.add(2)
            obj.m.add(2,4)
            obj.m.add(*[1,])
            
            删除:
            obj.m.remove(1)
            obj.m.remove(2,3)
            obj.m.remove(*[4,])
            
            覆盖修改:
            obj.m.set([1,])
            
            q = obj.m.all()
            # [Girl对象]
            print(q)
            obj = models.Boy.objects.filter(name='方少伟').first()
            girl_list = obj.m.all()
            
            obj = models.Boy.objects.filter(name='方少伟').first()
            girl_list = obj.m.all()
            girl_list = obj.m.filter(nick='小鱼')
            print(girl_list)
            
            删除第三张表的数据:
            obj = models.Boy.objects.filter(name='方少伟').first()
            obj.m.clear()
    
            反向操作:
            obj = models.Girl.objects.filter(nick='小鱼').first()
            print(obj.id,obj.nick)
            v = obj.boy_set.all()
            print(v)
            
            
    2.杂交:
    #m = models.ManyToManyField('Girl',through="Love",through_fields=('b','g',))
    obj = models.Boy.objects.filter(name='方少伟').first()
    # obj.m.add(1)        因为有ManyToManyField,所以不行,因为可能第三张表还有其他列
    # obj.m.remove(1)    因为有ManyToManyField,所以不行,因为可能第三张表还有其他列
    # obj.m.clear()     可以
    v = obj.m.all()        可以
    print(v)
                        
            
            
    3. 自定义关系表
    View Code

    多对多操作,有无第三张表的情况:

    # 自己反向关联,需要通多中间的表
            # v= models.Article.objects.filter(blog=blog,article2tag__tag=val)
            # 通过M2M字段,直接关联到另一张表,跳过中间件
            # v= models.Article.objects.filter(blog=blog,tags__nid=val)
    View Code
    class Article(models.Model):
        nid = models.BigAutoField(primary_key=True)
        title = models.CharField(verbose_name='文章标题',max_length=128)
        summary = models.CharField(verbose_name='文章简介',max_length=255)
        read_count = models.IntegerField(default=0)
        comment_count = models.IntegerField(default=0)
        up_count = models.IntegerField(default=0)
        down_count = models.IntegerField(default=0)
        create_time = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)
        blog = models.ForeignKey(verbose_name='所属博客',to='Blog',to_field='nid')
        category = models.ForeignKey(verbose_name='文章类型',to='Category',to_field='nid',null=True)
    
        type_choices=[
            (1,'Python'),
            (2,'Linux'),
            (3,'OpenStack'),
            (4,'GoLang'),
        ]
    
        article_type_id = models.IntegerField(choices=type_choices,default=None)
    
        tags = models.ManyToManyField(
            to = 'Tag',
            through='Article2Tag',
            through_fields=('article','tag'),
        )
    class Tag(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(verbose_name='标签名称',max_length=32)
        blog = models.ForeignKey(verbose_name='所属博客',to='Blog',to_field='nid')
    class Article2Tag(models.Model):
        article = models.ForeignKey(verbose_name='文章',to='Article',to_field='nid')
        tag = models.ForeignKey(verbose_name='标签',to='Tag',to_field='nid')
        class Meta:
            unique_together =[
                ('article','tag'),
            ]
    model


    分组: 

        """
        1. 分类
            category_list = models.Article.objects.filter(blog=blog).values('category_id','category__title',).annotate(c=Count('nid'))
        2. 标签
            tag_list = models.Article2Tag.objects.filter(tag__blog=blog).values('tag_id','tag__title').annotate(c=Count('id'))
        3. 时间
            # MySQL
            # date_list = models.Article.objects.filter(blog=blog).extra(select={'c': "date_format(create_time,'%%Y-%%m')"}).values('c').annotate(ct=Count('nid'))
            # SQLlite
            # date_list = models.Article.objects.filter(blog=blog).extra(select={'c': "strftime('%%Y-%%m',create_time)"}).values('c').annotate(ct=Count('nid'))
    
        """
        mysql:
        date_list = models.Article.objects.filter(blog=blog).values("date_format(create_time,'%%Y-%%m')").annotate(ct=Count('nid'))    #错误,values里面参数只能是列名
        # date_list = models.Article.objects.filter(blog=blog).extra(select={'c': "date_format(create_time,'%%Y-%%m')"}).values('c').annotate(ct=Count('nid')
    时间格式的处理


    类型处理:

    from django.db.models import functions
        # models.Article.objects.filter(blog=blog).annotate(x=functions.Extract('create_time','YEAR_MONTH'))
        # models.Article.objects.filter(blog=blog).annotate(x=functions.ExtractYear('create_time'))
        """
        nid xx   create_time            x
         1  x     2018-09-01 11:11      201809
         2  x     2018-09-01 11:11      2018
    
    
        """
        # models.Article.objects.filter(blog=blog).annotate(x=functions.TruncMonth('create_time'))
        # models.Article.objects.filter(blog=blog).annotate(x=functions.Trunc('create_time',''))
        """
        nid xx   create_time            x
         1  x     2018-09-01 11:11      09
    
    
        """
        # from django.db.models import FloatField
        # from django.db.models import Value
        # v = models.Article.objects.annotate(c=functions.Cast('nid', FloatField()))    #类型转换
        # v = models.Article.objects.annotate(c=functions.Coalesce('title','summary'))    #找到第一个非空
        # v = models.Article.objects.annotate(c=functions.Concat('nid','title','summary'))  #拼接
        # v = models.Article.objects.annotate(c=functions.Concat('nid','title','summary',Value('666')))
        # v = models.Article.objects.annotate(c=functions.Greatest('nid','num'))   #取较大的值
        # v = models.Article.objects.annotate(c=functions.Length('title'))            #获取长度
        # v = models.Article.objects.annotate(c=functions.Substr('title',1,1))        #取自定长度的字符串,只能从第一位开始
    ORM中的类型处理

    进阶操作:

    # 1.增删改查
                # 2. 一般:
                    # models.UserInfo.objects.filter(id__gt=1)  大于
                    # models.UserInfo.objects.filter(id__lt=1)    小于
                    # models.UserInfo.objects.filter(id__gte=1)    大于等于
                    # models.UserInfo.objects.filter(id__lte=1)    小于等于                
                    # models.UserInfo.objects.filter(id__in=[1,2,3])
                    # models.UserInfo.objects.filter(id__range=[1,2])
                    # models.UserInfo.objects.filter(name__startswith='xxxx')    以xxxx开头
                    # models.UserInfo.objects.filter(name__contains='xxxx')        内容包含xxxx
                            # models.UserInfo.objects.filter(name__icontains='xxxx')        内容包含xxxx,不区分大小写
    
                    # models.UserInfo.objects.exclude(id=1)        不等于exclude
                    models.UserInfo.filter(age__isnull=True)        数据为空也可以查询
                # 3. 排序
                    user_list = models.UserInfo.objects.all().order_by('-id','name')    反向排序
                    user_list = models.UserInfo.objects.all().order_by('id','name')        正向排序
                
                # 4. 分组
                    from django.db.models import Count,Sum,Max,Min
                    分组:
                    v =models.UserInfo.objects.values('ut_id').annotate(xxxx=Count('id'))    
                    print(v.query)
                    结果:
                    #SELECT "app01_userinfo"."ut_id", COUNT("app01_userinfo"."id") AS "xxxx" 
                        FROM "app01_userinfo" GROUP BY "app01_userinfo"."ut_id"
                    
                    分组后再筛选:
                    v =models.UserInfo.objects.values('ut_id').annotate(xxxx=Count('id')).filter(xxxx__gt=2)
                    print(v.query)
                    结果:
                    SELECT "app01_userinfo"."ut_id", COUNT("app01_userinfo"."id") AS "xxxx" 
                    FROM "app01_userinfo" GROUP BY "app01_userinfo"."ut_id" HAVING COUNT("app01_userinfo"."id") > 2
                    
                    v =models.UserInfo.objects.filter(id__gt=2).values('ut_id').annotate(xxxx=Count('id')).filter(xxxx__gt=2)
                    print(v.query)
                    结果:
                    SELECT "app01_userinfo"."ut_id", COUNT("app01_userinfo"."id") AS "xxxx" 
                        FROM "app01_userinfo" WHERE "app01_userinfo"."id" > 2 GROUP BY "app01_userinfo"."ut_id" 
                        HAVING COUNT("app01_userinfo"."id") > 2
                    
                
                
                5. F,更新时用于获取原来的值
                    from django.db.models import F,Q
                    更新数据库一列:
                    models.UserInfo.objects.all().update(age=F("age")+1)
                
                 6. Q,用于构造复杂查询条件
                    # 应用一:
                            # models.UserInfo.objects.filter(Q(id__gt=1))
                            # models.UserInfo.objects.filter(Q(id=8) | Q(id=2))
                            # models.UserInfo.objects.filter(Q(id=8) & Q(id=2))
                    # 应用二:
                            models.UserInfo.objects.filter(id=1,name='root')
                            condition = {
                                'id':1,
                                'name': 'root'
                            }
                            models.UserInfo.objects.filter(**condition)
                                        
                    
                            自动添加Q
                            condition_dict = {
                                'k1':[1,2,3,4],
                                'k2':[1,],
                            }
                            con = Q()
                            for k,v in condition_dict.items():
                                q = Q()
                                q.connector = 'OR'
                                for i in v:
                                    q.children.append(('id', i))
                                con.add(q,'AND')
                            models.UserInfo.objects.filter(con)
                            
                    
                            # q1 = Q()
                            # q1.connector = 'OR'
                            # q1.children.append(('id__gt', 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))
                            #
                            # q3 = Q()
                            # q3.connector = 'AND'
                            # q3.children.append(('id', 1))
                            # q3.children.append(('id', 2))
                            # q2.add(q3,'OR')
                            #
                            # con = Q()
                            # con.add(q1, 'AND')
                            # con.add(q2, 'AND')
                            
                            # models.UserInfo.objects.filter(con)
                
                # 7. extra, 额外查询条件以及相关表,排序
                
                    """
                        select
                            id,
                            name,
                            (select count(1) from tb) as n
                        from xb where ....
                    """
                
                
                    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 表
                     v = models.UserInfo.objects.all().extra(
                        select={
                            'n':"select count(1) from app01_usertype where id=%s or id=%s",
                            'm':"select count(1) from app01_usertype where id=%s or id=%s",
                        },
                        select_params=[1,2,3,4])
                    for obj in v:
                        print(obj.name,obj.id,obj.n)    
                    
                    
                    # b. 条件
                        # where=None
                        # params=None,
                        # select * from 表 where 此处
                        models.UserInfo.objects.extra(
                            where=["id=1","name='alex'"]
                        )
                        models.UserInfo.objects.extra(
                            where=["id=1 or id=%s ","name=%s"],
                            params=[1,"alex"]
                        )
                        
                    
                    # c. 表
                        # tables
                        # select * from 表,此处
                     models.UserInfo.objects.extra(
                        tables=['app01_usertype'],
                    )
                    """select * from app01_userinfo,app01_usertype"""
                    
                    # 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
    
    ORM操作进阶
    ORM进阶操作
    原生SQL语句
                    导入现成的连接
                    from django.db import connection, connections
                    
                    cursor = connection.cursor()             # connection=default数据库
                    cursor = connections['db2'].cursor()    #连接db2数据库
                    
                    cursor.execute("SELECT * from auth_user where id = %s", [1])                
                    row = cursor.fetchone()
                    row = cursor.fetchall()
    原生SQL语句
    ##################################################################
    # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
    ##################################################################
    
    def all(self)
        # 获取所有的数据对象
    
    def filter(self, *args, **kwargs)
        # 条件查询
        # 条件可以是:参数,字典,Q
    
    def exclude(self, *args, **kwargs)
        # 条件查询
        # 条件可以是:参数,字典,Q
    
    def 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) > 1
    
    def distinct(self, *field_names)
        # 用于distinct去重
        models.UserInfo.objects.values('nid').distinct()
        # select distinct nid from userinfo
    
        注:只有在PostgreSQL中才能使用distinct进行去重
        models.UserInfo.objects.distinct('nid')
        select distinct nid from userinfo
    
    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中的设置)
        models.UserInfo.objects.all().using('db2'),不指定就是默认的数据库
    
    
    ##################################################
    # 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):
        # 获取单个对象
         v = models.UserInfo.objects.all().first()  没有值就是NONE,推荐用这个
        # models.UserInfo.objects.get(id=1)            没有值就报错
    
    def create(self, **kwargs):
        方法一:
            # 创建对象,有返回值
            obj = models.UserType.objects.create(title='xxx')
            obj = models.UserType.objects.create(**{'title': 'xxx'})
            print(obj.id)
        方法二:
            obj = models.UserType(title='xxx')
            obj.save()
    
    def bulk_create(self, objs, batch_size=None):
        # 批量插入
        # batch_size表示一次插入的个数,最多不要超过99。
        objs = [
            models.UserInfo(name='r11'),
        ]
        models.UserInfo.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})
        obj是查询的返回值,created 返回Ture、or
    
    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):
       # 是否有结果
    其他操作
    - 其他:
                UserInfo.objects.all()
                UserInfo.objects.filter(id=1,id=2)
                UserInfo.objects.all().first()
                UserInfo.objects.all().count()
                UserInfo.objects.all().update()
                UserInfo.objects.all().delete()
                UserInfo.objects.all()[1:19]
                跨表:
                    正向:
                        xxxx.filter(ut__title='超级用户').values('id','name','ut__title')
                    反向:
                        xxxx.filter(表名称__title='超级用户').values('id','name','表名称__title')
                
    - 其他:

    XSS跨站脚本攻击

    XSS跨站脚本攻击

      恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。

    CSRF  跨站请求伪造

      CSRF则通过伪装来自受信任用户的请求来利用受信任的网站

    -   慎用 safe(在html中使用)<div>{{ item|safe }}</div>
      mark_safe(在后端使用)
    -      非要用,一定要过滤关键字
     

    在vews.py中
    from django.shortcuts import render
    msg = []
    
    def comment(request):
        if request.method == "GET":
            return render(request,'comment.html')
        else:
            v = request.POST.get('content')
            if "script" in v:
                return render(request,'comment.html',{'error': '小比崽子还黑我'})
            else:
                msg.append(v)
                return render(request,'comment.html')
    
    def index(request):
        return render(request,'index.html',{'msg':msg})
    
    def test(request):
        from django.utils.safestring import mark_safe
        temp = "<a href='http://www.baidu.com'>百度</a>"
        newtemp = mark_safe(temp)   #标记字符串为安全的
        return render(request,'test.html',{'temp':newtemp})
    
    
    
    
    
    在html中
    commom。html中
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <form method="POST" action="/comment/">
            <input type="text" name="content"/>
            <input type="submit" value="提交" />{{ error }}
        </form>
    </body>
    </html>
    
    index.html中
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <h1>评论</h1>
        {% for item in msg %}
            <div>{{ item|safe }}</div>
    //标记为安全
        {% endfor %}
    </body>
    </html>
    
    
    test.html中
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        {{ temp }}
    </body>
    </html>
    View Code

    分页

    分批获取数据
        models.UserInfo.objects.all()[0:10]
        models.UserInfo.objects.all()[10:20]

    - Django自带

    适合于:上一页下一页
    from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage
    def index(request):
        current_page = request.GET.get('page')
    
        user_list = models.UserInfo.objects.all()
        paginator = Paginator(user_list,10)
        # paginator.xxx
        # per_page: 每页显示条目数量
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象,显示第几页
        
        try:
            posts = paginator.page(current_page)
        except PageNotAnInteger as e:
            posts = paginator.page(1)
        except EmptyPage as e:
            posts = paginator.page(1)
        
        # posts.xxx                    
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             posts.paginator即paginator对象
        return render(request,'index.html',{'posts':posts})                    
        
        
    index.html    
    <h1>用户列表</h1>
    <ul>
        {% for row in posts.object_list %}
            <li>{{ row.name }}</li>
        {% endfor %}
    </ul>
    <div>
        {% if posts.has_previous %}
            <a href="/index.html?page={{ posts.previous_page_number }}">上一页</a>
        {% endif %}
        {% for num in posts.paginator.page_range %}
            <a href="/index.html?page={{ num }}">{{um}}</a>
        {% endfor %}
        {% if posts.has_next %}
            <a href="/index.html?page={{ posts.next_page_number }}">下一页</a>
        {% endif %}
    </div>
    View Code

    - 自定分页组件 

    views.py中
    from utils.pager import PageInfo
    def custom(request):
        # 数据控总行数
        all_count = models.UserInfo.objects.all().count()
    
        #实例化PageInfo,传值:当前页码、数据控总行数、每页显示个数、url前缀、一次能显示的页码数
        page_info = PageInfo(request.GET.get('page'),all_count,10,'/custom.html',11)
        user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()]
    
        return render(request,'custom.html',{'user_list':user_list,'page_info':page_info})
            
    utils下pager.py
    class PageInfo(object):
    
        def __init__(self,current_page,all_count,per_page,base_url,show_page=11):
            """
    
            :param current_page:
            :param all_count: 数据库总行数
            :param per_page: 每页显示函数
            :param show_page=11: 一次总共显示的页码
            :return:
            """
            try:
                self.current_page = int(current_page)
            except Exception as e:
                self.current_page = 1
            self.per_page = per_page
    
            a,b = divmod(all_count,per_page)
            if b:
                a = a +1
            self.all_pager = a      #判断总页数
            self.show_page = show_page
            self.base_url = base_url
    
        #当前页的开始值
        def start(self):
            return (self.current_page-1) * self.per_page
        #当前页的结束值
        def end(self):
            return self.current_page * self.per_page
    
    
        def pager(self):
            page_list = []
    
            half = int((self.show_page-1)/2)        #一次总共显示的页码数的一半,用于判断页码的起始值
    
            # 如果数据总页数 < 11
            if self.all_pager < self.show_page:
                begin = 1
                stop = self.all_pager + 1
            # 如果数据总页数 > 11
            else:
                # 如果当前页 <=5,永远显示1,11
                if self.current_page <= half:
                    begin = 1
                    stop = self.show_page + 1
                else:
                    if self.current_page + half > self.all_pager:
                        begin = self.all_pager - self.show_page + 1
                        stop = self.all_pager + 1
                    else:
                        begin = self.current_page - half
                        stop = self.current_page + half + 1
            first_page = "<li><a href='%s?page=1'>首页</a></li>" %(self.base_url,)
            page_list.append(first_page)
            if self.current_page <= 1:
                prev = "<li><a href='#'>上一页</a></li>"
            else:
                prev = "<li><a href='%s?page=%s'>上一页</a></li>" %(self.base_url,self.current_page-1,)
            page_list.append(prev)
    
            for i in range(begin,stop):
                if i == self.current_page:   #当前页改变背景色
                    temp = "<li class='active'><a  href='%s?page=%s'>%s</a></li>" %(self.base_url,i,i,)
                else:
                    temp = "<li><a href='%s?page=%s'>%s</a></li>" %(self.base_url,i,i,)
                page_list.append(temp)    #将字符串追加进列表
    
            if self.current_page >= self.all_pager:
                nex = "<li><a href='#'>下一页</a></li>"
            else:
                nex = "<li><a href='%s?page=%s'>下一页</a></li>" %(self.base_url,self.current_page+1,)
            page_list.append(nex)
    
            last_page = "<li><a href='%s?page=%s'>尾页</a></li>" % (self.base_url,self.all_pager)
            page_list.append(last_page)
    
    
            return ''.join(page_list)
            
            
    html文件:
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title></title>
            <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" />
        </head>
        <body>
            <h1>用户列表</h1>
            <ul>
                {% for row in user_list %}
                    <li>{{ row.name }}</li>
                {% endfor %}
            </ul>
    
            <nav aria-label="Page navigation">
              <ul class="pagination">
                  {{ page_info.pager|safe }}
                  //自动执行实例化对象的下的函数,传过来是字符串,因为XSS攻击不能渲染成字符串,加safe即可
              </ul>
            </nav>
        </body>
        </html>
    View Code

     CBV & FBV 

    url---->class        CBV 
        url---->function    FBV
        
        from app01 import views
        urlpatterns = [
            url(r'^admin/', admin.site.urls),        
            url(r'^login.html$', views.Login.as_view()),    
        ]
        
        
        from django.views import View
        class Login(View):
            """
            get     查
            post    创建
            put     更新
            delete  删除
            ajax可以有除了get、post的其他提交方法
            """
            
            #定制自己的dispatch,判断客户端发送过来数据的方法
            def dispatch(self, request, *args, **kwargs):
                print('before')
                obj = super(Login,self).dispatch(request, *args, **kwargs)   #继承父类的dispatch
                print('after')
                return obj
    
            def get(self,request):
                # return HttpResponse('Login.get')
                return render(request,'login.html')
    
            def post(self,request):
                print(request.POST.get('user'))
                return HttpResponse('Login.post')
    View Code

     http://www.bubuko.com/infodetail-1972338.html

  • 相关阅读:
    问题-Delphi在多线程中使用其他窗体上的控件,报“尚未调用CoInitialize”解决方法
    问题-Delphi不能进行调试模式
    问题-Delphi为什么不能连接oracle
    问题-delphi无法编辑oracle表
    问题-[致命错误] Project1.dpr(1): Unit not found: 'System.pas' or binary equivalents (DCU,DPU)
    问题-Delphi编译时提示缺少delphi自己的单元文件
    教程-Delphi7 自带控件安装对应表
    问题-提示“adodataset.command”
    问题-提示“不正常地定义参数对象。提供了不一致或不完整的信息。”
    问题-[Delphi]提示Can't load package:dclite70.bpl解决方法
  • 原文地址:https://www.cnblogs.com/domestique/p/7077279.html
Copyright © 2011-2022 走看看