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

相關文章
相關標籤/搜索