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

原文地址:https://www.cnblogs.com/domestique/p/7077279.html