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语句进行优化css

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

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

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的操做:mysql

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语句
一对一操做的正反向:ajax

 # 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操做

多对多操做:有外键的状况查询操做sql

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

多对多操做,有无第三张表的状况:django

# 本身反向关联,须要通多中间的表
        # 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


分组: bootstrap

    """
    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

相关文章
相关标签/搜索