Django總結四

0.ORM操做

一、必會的13條html

  • 返回對象列表的python

    • allajax

    • filter數據庫

    • excludedjango

    • order_byjson

    • reverse數組

    • distinct瀏覽器

  • 特殊的對象列表緩存

    • values安全

    • values_list

  • 返回對象的

    • get

    • first

    • last

  • 返回布爾值

    • exist

  • 返回數字的

    • count

二、單表中雙下滑線

    • __gt

    • __lt

    • __in

    • __range

    • __countains

    • __icountains

    • __startswith

    • __istartswith

    • __endswith

    • __iendswith

    • __isnull

1.一對多(外鍵的查詢)

正向查詢

按照對象查詢,這個時候只要屢清楚外鍵設置在哪一個方向,按照對象一步一步的

往過屢就ok。

 

反向查詢

反向查詢的時候經過表名(小寫的類名)_set,拿到這個管理對象,對這個對象

能夠進行表的一些操做。

 

按字段查詢

按字段查詢的時候就沒有必要屢主外鍵在哪方面,只須要看着要查的結果和條件

而後按雙下劃線方法去查找就ok

 

例子:

# 查找書名是「1」的書的出版社出版的其餘書籍的名字和價格
ret = models.Publisher.objects.filter(book__title='1').first().books.exclude(title='1').values('title','price')
print(ret)

ret = models.Book.objects.filter(publisher=models.Publisher.objects.filter(book__title='1').first()).exclude(
   title='1')
print(ret)


# 查找書名是「1」的書的做者們的姓名以及出版的全部書籍名稱和價錢

ret = models.Author.objects.values('book__title', 'book__price').filter(book__title='1').distinct()

for i in ret:
   print(i)

# ret = models.Book.objects.get(title='1').author.values('name', 'book__title', 'book__price').distinct()
# print(ret)

查出的數據確定是一條一條的,若是是一對多條,會一行一行的列出來嗎,而後 再篩選

 

2.多對多

正向查詢

Obj.多對多關係 -》 管理對象

add()

remove()

clear()

set() []

create()

反向查詢

Obj.表名(小寫的類名)_set -》 管理對象

3.聚合 aggregate

聚合是一個終止語句 aggregate

4.分組 annotate

分組的目的是爲了進行聚合操做

分組的結果放到了字段中(values中)

正着來

若是不指定分組對象,那麼按照表名(表名id)分

反着來

這樣是指定values(字段)(也就是分組名稱)來分組

拿到的是對象

5.F查詢

from django.db.model import F

兩個字段之間的比較

子段__gt=F("字段")

字段=F(「字段」) * 2

字段=Concat(F("title"), Value("("), Value("初版"), Value(")"))

6.Q查詢

from django.db.model import Q

兩個條件之間的或關係

Q(篩選條件) | Q(篩選條件)

二者條件之間的與關係

Q(篩選條件) & Q(篩選條件)

條件取反

~Q(篩選條件)

7.事務

把一些列的操做(步驟)看成一個事務

所有的步驟都成功才成功

經典例子:銀行轉帳

 

代碼實現:

import os

if name == 'main': ​ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") ​ import django ​ django.setup()

import datetime
from app01 import models

try:
   from django.db import transaction  # 事務
   with transaction.atomic():  # 裏面是執行的全部步驟
       new_publisher = models.Publisher.objects.create(name="火星出版社")
       models.Book.objects.create(title="橘子物語", publish_date=datetime.date.today(), publisher_id=10)  # 指定一個不存在的出版社id
except Exception as e:
   print(str(e))

 

 

Cookie

 

  • 是一個保存在瀏覽器本地的一組組鍵值對

  • 爲何用cookie?http協議是無狀態的,每次請求都是無關聯的,沒有辦法保存狀態

  • Network中,請求頭中(隨着request傳到服務器)

  • 禁用以後登錄不了,登錄是配合cookie作的

  • 特性

    • 服務器讓瀏覽器進行保存的cookie

    • 瀏覽器有權利是否進行保存

    • 再次訪問服務器的時候會攜帶相應的cookie

  • Django使用

    • 獲取

      • request.COOKIES

    • 設置

      • ret = HttpRequest("XXX")

      • ret.set_cookie(key, max-age=5)

    • 刪除

      • ret = HttpResponse("XX")

      • ret.delete_cookie(key)

  • 用途

    • 登陸

    • 投票

    • 記錄瀏覽習慣

 

 

Session

 

  • 保存着服務器上的鍵值對

  • 爲何要用session?

    • cookie保存在瀏覽器上,不安全、

    • cookie的長度受限制 4096字節

  • Django中操做session

    • 設置session

      • request.session[key] = value

      • request.session.setdefault(key, valuue)

    • 獲取session

      • request.session[key]

      • request.session.get(key)

    • 刪除session

      • del request.session[key] 刪除某一個

      • request.session.delete() 刪除該用戶的全部數據,不刪除cookie

      • request.session.flush() 刪除該用戶的全部數據,刪除cookie

    • 設置超時時間

      • request.session.set_expiry(value)

    • 清除全部過時的session

      • request.session.clear_expired()

 

SESSION的配置

 

  • from django.conf import global_settings

  • SEESSION配置

  • 458行

    • SESSION_COOKIE_NAME 名字

    • SESSION_COOKIE_AGE 過時時間

    • SESSION_SAVE_EVERY_REQUEST = False 每次保存一次session

    • SESSION_EXPIRE_AT_BROWSER_CLOSE = False 關閉瀏覽器就清除cookie

    • SESSION_ENGINE = '' 設置引擎

      • Django中默認支持session,其內部提供了5種類型的session供開發者使用

        1. 數據庫Session
        SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默認)

        2. 緩存Session
        SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
        SESSION_CACHE_ALIAS = 'default'                            # 使用的緩存別名(默認內存緩存,也能夠是memcache),此處別名依賴緩存的設置

        3. 文件Session
        SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
        SESSION_FILE_PATH = None                                    # 緩存文件路徑,若是爲None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir()

        4. 緩存+數據庫
        SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

        5. 加密Cookie Session
        SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
      • 其餘公用設置項:
        SESSION_COOKIE_NAME "sessionid"                       # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認)
        SESSION_COOKIE_PATH "/"                               # Session的cookie保存的路徑(默認)
        SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默認)
        SESSION_COOKIE_SECURE = False                            # 是否Https傳輸cookie(默認)
        SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http傳輸(默認)
        SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默認)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否關閉瀏覽器使得Session過時(默認)
        SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次請求都保存Session,默認修改以後才保存(默認)

 

 

中間件

 

發請求:a標籤,location,form表單,地址欄

鉤子:在某個位置預留了位置,沒有掛鉤子函數的話繼續執行,若是寫了鉤子函數就執行完後繼續執行。

  • 中間件全部的動做都會走,會影響全局,謹慎使用

  • settings中的MIDDLEWARE

  • Django中的中間件?是什麼?

    • 是一個python類用來在全局範圍內處理請求和響應的一個鉤子。

  • 自定義中間件

    • 五個方法

      • 參數,執行時間,執行順序

      • 一、process_request(self, request)

        • 執行時間:在路由匹配以前,在視圖函數執行以前,

        • 參數:

          • request:視圖函數用到中用到的request

        • 執行順序:按照註冊順序執行

        • 返回值:

          • None:正常流程

          • HttpResponse對象:當前中間件後面的中間件的process_request方法

            process_Response方法和視圖的Http_Response對象不執行,執行當前

            中間件的process_response方法以及以前的process_reques方法

      • 二、process_response(self, request, response)

        • 執行時間:在視圖函數執行以後

        • 參數:

          • request:視圖函數用到中用到的request

          • response:視圖函數中返回的response對象,若是中間件返回response對象,就不走

            視圖函數了

        • 執行順序:按照註冊順序倒序執行

        • 返回值:

          • 不能爲None,不然會報錯

          • 必須是response對象

      • 三、process_view(self, request, view_func, view_args, view_kwargs)

        • 執行時間:在視圖函數以前,在process_reques方法以後,以及路由匹配以後

        • 參數:

          • request:視圖函數用到中用到的request

          • view_func:要執行的視圖函數

          • view_args:視圖函數的位置參數

          • view_kwargs:視圖函數的關鍵字參數

        • 返回值:

          • None:正常流程

          • HttpResponse對象:他以後的中間件process_view方法、視圖都不執行,執行全部中

          • 間件的process_response方法

        • 執行屬性:按照註冊順序執行

      • 四、process_exception(self, request, exception)

        • 執行時間:

          • 觸發條件:有異常才執行

          • 在視圖函數以後,在process_response以前

        • 參數:

          • request:視圖函數用到中用到的request

          • exception:錯誤信息對象

        • 返回值:HttpResponse對象:

          • None:正常執行

          • HttpResponse對象:

            • 註冊順序以前的全部中間件的process_exception方法不走了

            • 執行全部中間件的的process_response

        • 執行順序:按照註冊順序倒序執行

      • 五、process_template_response(self, request, response)

        • 執行時間:

          • 觸發條件:返回的response對象要有一個render方法

          • 在視圖函數以後,在process_response方法以前

        • 參數「

          • request:視圖函數用到中用到的request

          • response:視圖函數中返回的response對象

        • 返回值:

          • 不能爲None,不然會報錯

          • 必須是response對象

        • 執行順序:按照註冊順序倒序執行(不會截斷,可以重寫)

  • CSRF中間件

    • CSRF跨站請求僞造

  • 在form表單中加{%csrf_token%}幹了兩件事

    • 隱藏一個input標籤

    • 生成一個cookie

  • 兩個裝飾器

    • from django.views.decorators.csrf import csrf_exempt, csrf_protect

      • csrf_exempt:給單個視圖排除校驗

      • csrf_protect:給單個視圖必須校驗

  • 源碼分析

    • process_request

      • 從請求的cookie中獲取csrftoken的值 ——》csrf_token ——》

        request.META['CSRF_COOKIE']

    • preocess_view

      • 若是視圖函數加上了csrf_exempt的裝飾器 不作校驗

      • 若是請求方式是'GET', 'HEAD', 'OPTIONS', 'TRACE' 也不作校驗

      • 其餘的請求方式作校驗

        • request.META.get('CSRF_COOKIE') —— 》 csrf_token

           

          request_csrf_token = ""

          從request.POST中獲取csrfmiddlewaretoken對應的值

          request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')

          從請求頭中獲取X-csrftoken 的值

          request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')

           

          request_csrf_token 和 csrf_token 作對比

          若是校驗成功 正常走

          若是校驗不成功 拒絕

  • 瀏覽器向服務器發送請求的形式

    • 地址欄輸入地址 回車 GET

    • form表單 點擊 submit

    • a標籤

    • ajax

json

 

  • json是一種數據結構,跨平臺

  • python中的json數據結構轉換

    • 數據類型

      • 字符串、數字、bool、列表、字典、None

    • 序列化

      • dumps(python數據類型)

      • dump(python的數據類型, f)

    • 反序列化

      • loads

      • load

  • js中json數據的轉換

    • 數據類型

      • 字符串、數字、布爾、數組、對象、null

    • 序列化

      • stringify

    • 反序列化

      • parse

  • django中json

    • JsonResponse

      • JsonResponse({})

      • JsonResponse([], safe=False)

ajax

  • 是一個與服務器進行交互的技術。(js技術)

  • 特色:

    • 異步

    • 不刷新頁面 數據量小

  • 瀏覽器向服務器發送請求

    • 地址欄輸入地址 回車

    • form表單

    • a標籤

    • ajax

  • ajax

    • 參數

      $('#b1').click(function () {
      $.ajax({
      url: '/calc/',             # url地址
      type: 'post',   # 請求方式
      data: {                    # 發送的數據  
      i1: $('[name="i1"]').val(),
      i2: $('[name="i2"]').val()
      hobby:JSON.stringify(['抽菸','喝酒','燙頭'])   # 傳個列表 進行序列化

      },
      success: function (res) {         # 回調函數   成功時調用 res 返回的內容 響應的響應體
      console.log(res);
      $('[name="i3"]').val(res)

      }, error: function (res) {        # 回調函數 失敗時調用


                     console.log('這是錯誤的')
                     console.log(res)
                }

      })
      });
  • ajax發post請求 經過CSRF驗證的方法

    • 頁面中使用{% csrf_token %}

      $('#b1').click(function () {
      $.ajax({
      url: '/csrf_test/',
      type: 'post',
      data: {
      csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val(),  # **********
      name: 'ward',
      age: '18',
      },
      success: function (res) {
      console.log(res);
      }
      })
      });
    • 設置請求頭

    • $('#b1').click(function () {
      $.ajax({
      url: '/csrf_test/',
      type: 'post',
      headers: {"X-CSRFToken": $('[name="csrfmiddlewaretoken"]').val()},
      data: {
      name: 'ward',
      age: '18',
      },
      success: function (res) {
      console.log(res);
      }
      })
      });
    • 全局設置(本身寫的js代碼)

      function getCookie(name) {
         var cookieValue = null;
         if (document.cookie && document.cookie !== '') {
             var cookies = document.cookie.split(';');
             for (var i = 0; i < cookies.length; i++) {
                 var cookie = jQuery.trim(cookies[i]);
                 // Does this cookie string begin with the name we want?
                 if (cookie.substring(0, name.length + 1) === (name + '=')) {
                     cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                     break;
                }
            }
        }
         return cookieValue;
      }
      var csrftoken = getCookie('csrftoken');

      function csrfSafeMethod(method) {
       // these HTTP methods do not require CSRF protection
       return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
      }

      $.ajaxSetup({
       beforeSend: function (xhr, settings) {
         if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
           xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
      }
      });

       

      # 從cookie中取值 必要有cookie
      有cookie的方式
      1. 使用{% csrf_token %}
      2. 不使用{% csrf_token %}
      from django.views.decorators.csrf import ensure_csrf_cookie
      將ensure_csrf_cookie加在視圖上 保證返回的響應有cookie

       

auth模塊

 

  • 建立超級用戶

    • python3 manager.py createsuperuser

  • 認證 校驗 用戶的用戶名與密碼

    obj = auth.authenticate(request, username=username, password=password)

    認證成功:對象

    認真失敗:None

  • 保存登陸狀態 記錄到session

    login(request, user)
  • 註銷 刪除session

    logout(request)
  • 判斷登陸狀態

    requset.user.is_authenticated()
  • 建立用戶

    from django.cotrib.auth.models import User
    • 密碼是明文的

      User.objects.create(username=username,password=password)
    • 密碼是密文的普通用戶

      User.objects.create_user(**form_obj.cleaned_data)
    • 建立超級用戶

      User.objects.create_superuser(email='',**form_obj.cleaned_data)
  • 密碼相關

    • 校驗密碼

      request.user.check_password('root1234')
    • 設置密碼

      request.user.set_password('admin1234')
      request.user.save()
    • 擴展默認的auth_user表

    這內置的認證系統這麼好用,可是auth_user表字段都是固定的那幾個,我在項目中無法拿來直接使用啊!

    好比,我想要加一個存儲用戶手機號的字段,怎麼辦?

    可能會想到新建另一張表而後經過一對一和內置的auth_user表關聯,這樣雖然能知足要求可是有沒有更好的實現方式呢?

    答案是固然有了。

    咱們能夠經過繼承內置的 AbstractUser 類,來定義一個本身的Model類。

    這樣既能根據項目需求靈活的設計用戶表,又能使用Django強大的認證系統了。

    from django.contrib.auth.models import AbstractUser
    class UserInfo(AbstractUser):
      """
      用戶信息表
      """
      nid = models.AutoField(primary_key=True)
      phone = models.CharField(max_length=11, null=True, unique=True)
       
      def __str__(self):
          return self.username

    注意:

    按上面的方式擴展了內置的auth_user表以後,必定要在settings.py中告訴Django,我如今使用我新定義的UserInfo表來作用戶認證。寫法以下:

    # 引用Django自帶的User表,繼承使用時須要設置
    AUTH_USER_MODEL = "app名.UserInfo"

    再次注意:

    一旦咱們指定了新的認證系統所使用的表,咱們就須要從新在數據庫中建立該表,而不能繼續使用原來默認的auth_user表了。

Form組件

 

  • form

    • 完成的事情

      • 有input標籤,讓用戶能夠填數據

      • 校驗form表單提交數據

      • 提示錯誤信息

  • Django的form

    • 定義

      from django import forms

      # 定義form
      class RegForm(forms.Form):
         user = forms.CharField(label='用戶名')
         pwd = forms.CharField(label='密碼')
    • 使用

      • 視圖中

        def register2(request):
           form_obj = RegForm()
           return render(request, 'register2.html', {'form_obj': form_obj})
      • 模板中

            <form action="" method="post">
              {% csrf_token %}
              {{ form_obj.as_p }}
               <p>
                   <input type="submit" value="註冊">
               </p>
           </form>
            <form action="" method="post">
               <p>
                  {{ form_obj.user.lable }}
                  {{ form_obj.user }}
               </p>
               <p>
                  {{ form_obj.pwd.lable }}
                  {{ form_obj.pwd }}
               </p>
               <p>
                   <input type="submit" value="註冊">
               </p>

           </form>

        總結:

        form_obj.as_p ——> 自動生成多個p標籤 包含lable input框

        form_obj.user/form_obj.pwd ——> 自動生成某個字段的input框

        form_obj.user.errors ——> 某個字段的全部錯誤信息

        form_obj.user.errors.0 ——> 摸個字段的錯誤信息的第一個

        form_obj.use.id_for_lable

    • 字段和參數

      • 參數

        label='用戶名', # 標籤的名字 min_length=6, # 校驗的規則 最小長度 initial='alexdsb', # 初始值 error_messages={ # 自定義錯誤提示 'min_length': '你的長度過短了,還不到6', 'required': '不能爲空'

        } widget=widgets.PasswordInput() # 插件 指定字段的類型

    • 校驗

      • 每一個字段有默認的校驗方法

        min_length=6

        max_length=6

        required=False

        disabled 是否不可修改

      • 自定義校驗規則

        validators = [ 校驗器1,校驗器2 ]

        1. from django.core.validators import RegexValidator

          RegexValidator(r'^1[3-9]\d{9}$', '手機號不正經')

          1. 自定義函數 from django.core.exceptions import ValidationError

            def check_name(value): if 'sb' in value: raise ValidationError('不符合社會主義核心價值觀')

            validators = [ check_name, ]. # 校驗函數

      • 鉤子函數

        • 局部鉤子

          def clean_phone(self):
          value = self.cleaned_data.get('phone')
          if re.match(r'^1[3-9]\d{9}$',value):
          return value
          raise ValidationError('手機號不正經')
        • 全局鉤子

          def clean(self):
             pwd = self.cleaned_data.get('pwd')
             re_pwd = self.cleaned_data.get('re_pwd')

             if pwd == re_pwd:
                 return self.cleaned_data
             self.add_error('re_pwd','兩次密碼不一致')
             raise ValidationError('兩次密碼不一致')
相關文章
相關標籤/搜索