Python筆記整理 - Django

Django Reinhardt.jpg

Django 系統

環境搭建

  • anaconda + pycharm
  • anaconda使用
    • conda list : 顯示當前環境安裝的包
    • conda env list : 顯示安裝的虛擬環境列表
    • conda create -n env_name python=3.6 如:conda create -n tl_django python=3.6
    • 激活conda的虛擬環境
      • source activeate env_name (Linux下激活)
      • conda activate env_name (Windows下激活) 如: conda activate tl_django
      • 激活的含義是:進入某環境專用命令行界面, 并針對該環境進行設置
  • Django安裝:
    • conda activate tl_django (首先激活Django的環境, PS:激活后命令行前面回帶一個(tl_django)這樣的前綴)
    • pip install django==1.8

后臺流程

Django.png

創建第一個Django程序

  • django-admin startproject tulingxueyuan (創建Django項目: tulingxueyuan)

命令行啟動:

  • cd tulingxueyuan
  • python manage.py runserver (啟動服務器)

PyCharm啟動

  • 1.配置python環境:
    • 點擊File菜單 -> Settings -> Project:Python -> Project Interpreter-> “小齒輪”圖標 -> ADD -> Conda Environment -> Existing environment-> “...” 圖標 ->
      • Linux系統:
        Anaconda安裝路徑下的/envs/相應的虛擬環境名稱/bin/python.sh
      • Windows系統:
        1、 C:\Users\用戶名\Anaconda3\envs\相應的虛擬環境名稱\python.exe
        2、 C:\ProgramData\Anaconda3\envs\相應虛擬環境名稱\python.exe
        3、 C:\Users\rocka.conda\envs\相應虛擬環境名稱\python.exe
        Windows情況有點特殊,我分別在以上三個位置找到過。
      • 注意:剛剛配置好的環境,PyCharm還會把各種包整理一下,當IDE主界面右下方有一條細細的進度條在跑的時候,說明環境還在Update中尚未準備就緒,程序中某些import 包的語句還會被語法提示器認為是錯誤語句,此時要耐心等待。
  • 2.配置manage.py文件:
    • 鼠標指向manage.py文件-> 直接點運行 -> 將會報錯
    • 此時需要點界面右上角下拉菜單(位于啟動按鈕左邊) -> 選 Edit Configurations ->在Parameters輸入參數: runserver -> 確定 -> 出來后點運行即可

路由系統 - urls

  • 創建app
    • app: 負責一個具體業務或者一類具體業務的模塊
    • python manage.py startapp teacher (在app根目錄下執行,生成一個teacher的目錄,即teacher路由)
  • 路由
    • 按照具體的請求url, 導入到相應的業務
    • django的信息控制中樞
    • 本質上就是接受URL和相應的處理模塊的一個映射


      03A.png
    • 在接受URL請求的匹配上使用了RE
    • URL的具體內容在urls.py文件中 (閱讀該文件的代碼,發現內部是使用正則在處理URL和對應模塊的對應關系)
  • 需要關注的兩點:
    • 接受的URL是什么, 即如何用RE對傳入的URL進行匹配
    • 已知URL匹配到哪個處理模塊
  • URL匹配規則:
    • 從上到下一個一個比對
    • URL格式是分級格式,則按照級別一級一級往下比對,主要對應URL包含子URL的情況
    • 子URL一旦被調用,則不會返回到主URL
      • '/one/two/three/'
    • 正則以r開頭, 表示不需要轉義, 注意尖號(^)和美元符號($)
      • '/one/two/three' 配對正則: r'^one/'
      • '/oo/one/two/three' 不配對正則: r'^one/'
      • '/one/two/three/' 配對正則: r'^three/$
      • '/oo/one/two/three/oo/' 不配對正則: r'three/$'
      • 第一個反斜杠并不需要(系統自動忽略)
    • 如果從上到下都沒有找到合適的匹配內容,則報錯

2. 正常映射

  • 把某一個符合RE的URL映射到事務處理函數中去
  • 舉例如下:
    from showeast import views as sv
    urlpatterns = [
            url(r'admin/',adming.site.urls),
            url(r'^normalmap/', sv.normalmap),
    ]
    

3.URL 中帶參數映射

  • 在多事件處理代碼中需要由URL傳入參數,形如/myurl/param中的param

  • 參數都是字符串形式,如果需要整數等形式需要自行傳喚

  • 統稱的形式如下:

    /search/page/432 中的432需要經常性變化內容,就是參數

  • 一個較為復雜的例子:

    url(r'^withparam/(?P<year>[0-9])/(?P<month>[0,1][0-9)',tv.withparam)

    • 尖號表示從字符串左邊第一個字符開始匹配
    • 圓括號表示的是一個參數,里面的內容作為參數傳遞給被調用的函數
      參數名稱以問號加大寫P開頭嗎,尖括號里面就是參數的名字
      后面花括號表示出現的次數,此處的4 表示只能出現4個0-9的數字

4. URL在APP中處理

如果所有應用URL都集中在tulingxueyuan/urls.py中,可能導致文件臃腫
可以把urls具體功能逐漸分散到每個app中
- 從djanco.conf.urls導入include
- 注意此時RE部分的寫法
- 添加include 導入
- 使用方法:
確保include被導入
- 在根目錄的urls.py中寫url (1個功能模塊只對應1個url)
- 寫子路由 (功能模塊里的子模塊,在各自的文件夾內的:模塊名_url.py內添加)
- 編寫各個功能模塊的views函數,包括各個子路由的views函數
- 與直接在主urls.py中寫理由一樣,分散在各個模塊文件夾下面寫獨立的子路由,同樣可以使用參數

5. URL中嵌套參數

  • 捕獲某個參數的一部分
  • 例如URL /index/page-3 , 需要捕獲數字3作為參數
    1. url(r'index_1/(page-(\d+)/)?$, sv.myindex_1)
    2. url(r'index_2/(?:page-(?P<page_number>\d+)/)?$', sv.myindex_2)
    3. url(r'^book/page-(?P<pn>\d)/$', tv.do_param2)
    • 以上就是指從一個參數中再提煉一個參數(我個人認為第三個正則更簡單明了一些)

6. 傳遞額外的參數

  • 參數不僅僅來自于URL, 還可能是我們自己定義的內容
    url(r'extrem/$',sv.extremParam,{'name':'liuying'}),
  • 附加參數同樣適用于include語句, 此時對include內所有都添加.

7.URL的反向解析 reverse

  • 防止硬編碼
  • 本質上是對每一個URL進行命名
  • 以后在編碼代碼中使用URL的值,原則上都應該使用反向解析
  • reverse的好處是,只要給一個路由設好名字, 無論URL怎么變, 都可以用名字來引用,方便,主要用于模版

VIEWS 視圖

1. 視圖概述

  • 視圖即視圖函數,接受WEB請求返回WEB相應的事務處理函數.
  • 響應指符合http協議要求的任何內容,包括json, string, html等
  • 本章忽略事務處理, 重點在如何返回處理結果上

2. 其他簡單視圖

  • django.http為我們提供了很多和HttpResponse類似的簡單視圖,
    通過查看django.http的源代碼我們直到.
  • 此類視圖使用方法基本類似,可以通過return語句直反饋給瀏覽器
  • Http404為Exception子類, 所以需要用raise來顯式調用
  • Debug模式的關閉:
    • 打開根路徑下settings.py文件
    • 將Debug = True 改為 False
    • ALLOWED_HOSTS 改為 ["*"] (允許所有主機訪問)

3. HttpResponse詳解

  • 方法:
    • init : 使用頁內容實例化HttpResponse對象
    • write(content) : 以文件的方式寫
    • flush(): 以文件的方式輸出緩存區
    • set_cookie(key, value='', max_age = none,expires = None): 設置cookie
      • key , value 是字符串類型
      • max_age 是一個整數, 表示在指定秒數后過期
      • expires 是一個datetime或timedelta對象, 會話將在這個指定的日期/時間過期
      • max_age 和 expires , 二選一
      • 如果不指定過期時間,則兩個星期后過期
      • delete_cookie(key): 刪除指定的key的Cookie, 如果key不存在, 也不會報錯
4.png

4. HttpRespnseRedirect

  • 重定向, 服務器端跳轉
  • 構造函數的第一個參數用來指定重定向的地址
  • 例子: ShowViews/views.py
  • 在east/urls中添加以下內容:
            url(r'^v10_1/', views.v10_1),
            url(r'^v10_2/', views.v10_2),
            url(r'^v11/"' views.v11, name = "v11"),
            
           # /east/ShowViews/views 中添加以下內容
           def v10_1(request):
                return HttpRespnseRedirect("/v11")
           def v10_2(request):
                return HttpRespnseRedirect(reverse("v11"))
            def v11(request):
                return HttpRespnseRedirect(""這是v11 的返回值")
5.png

5.Request 對象

  • Request介紹

    • 服務器接受到http協議的請求后,會根據報文創建HttpRequest對象
    • 視圖函數的第1個參數就是HttpRequest對象(在Python中,形參只跟位置相關,而跟具體的參數名無關,例如self亦是如此)
    • 在django.http模塊中定義了HttpRequest對象的API
  • 屬性

    • 下面除非特別說明,屬性都是只讀的 (就像你給張三寫一封信, 張三收到后就已經沒有修改的意義了)
    • path : 一個字符串, 表示請求頁面的完整路徑, 不包含域名
    • method : 一個字符串,表示使用的HTTP方法,常用時包括:'GET'/'POST'
    • encoding : 一個字符串,表示提交的數據的編碼方式
      • 如果為None則表示使用瀏覽器的默認設置,一般為utf-8
      • 這個屬性是可寫的,可以通過修改他來修改訪問表單數據使用的編碼
    • GET : 一個類似字典的對象, 包含get請求方式的所有參數
    • POST : 一個類似字典的對象, 包含post請求方式的所有參數
    • FILES : 一個類似字典的對象, 包含所有的上傳文件
    • COOKIES : 一個標準的Python字典, 包含所有cookie, 鍵和值都包含其中
    • session: 一個即可獨有可寫的類似于字典的對象,表示當前會話.
      - 只有當Django啟用會話時才可用.
      - 詳細內容見"狀態保持".
  • 方法

    • is_ajax() : 如果請求是通過XMLHttpRequest發起的,則返回True
  • QueryDict 對象 [這個是Django特設的對象,HTTP本身沒有]

    • 定義在django.http.QueryDict里
    • request對象的屬性GET, POST都是QueryDict類型的對象
    • 與Python 字典不同,QueryDict類型的對象用來處理同一個鍵帶多個值的情況.
    • 方法get(): 根據鍵取值
      • 只能獲取鍵的一個值
      • 如果一個鍵同時擁有多個值,獲取最后一個值
    • 方法getlist():根據鍵獲取值
      • 將鍵的值以列表返回,可以獲取一個鍵的多個值
  • GET屬性 [此對象對應http協議的GET操作]

    • QueryDict類型的對象
    • 包含get請求方式的所有參數
    • 與url請求地址中的參數隊形,位于?后面
    • 參數的格式是鍵值對,如key1 = value1
    • 多個參數之間,用&鏈接,如key1=value1&key2=value2
    • 鍵是開發人員定下來的,值是可變的
    • 例子: ShowViews/views/v8_get
  • POST 屬性

    • QueryDict類型的對象
    • 包含post請求方式的所有參數
    • 與form表單中的空間對應
    • 表單中的控件必須有name屬性,name為鍵,value為值
      • checkbox存在一鍵多值的問題
    • 鍵是開發人員定下來的,值是可變的
    • 例子 ShowViews/views/v9_post
      • setting中設置模版位置, 在根目錄下建立一個templates文件夾,然后在setting.py里修改為:

        *('DIRS': [os.path.join(BASE_DIR,"templates")],)
        - setting中CRSF跨站攻擊防護要關閉,此行需要注釋掉)
        > * django.middleware.csrf.CsrfViewMiddleware',
        - 設置get頁面的urls和參數
        需要在路由文件中添加兩個路由:
        > * url(r'^v9_get/', v.v9_get),
        > * url(r'^v9_post/', v.v9_post),

  • 手動編寫視圖

    • 實驗目的:

    • 利用django快捷函數手動編寫視圖處理函數

    • 編寫過程中理解視圖運行原理

    • VIEW的目的:
      1.. 業務處理
      2.. 返回Respongse子類步驟:
      1. 拿到模版
      2. 拿到數據
      3. 環境變量(插入到HTML代碼中,以此定位數據填充的位置)
      4. 返回

    • 分析:

      • django把所有請求信息封裝入request
      • django通過URLS模塊把相應請求跟時間處理函數鏈接起來, 并把request作為參數傳入.
      • 在相應的處理函數中,我們需要完成兩部分
        1. 處理業務
        2. 把結果封裝并返回,我們可以使用簡單HttpResponse, 同樣也可以自己處理此功能
      • 本例子不介紹業務處理, 把目光集中在如何渲染結果并返回
    • render(request, templater_name [,context][,context_omstamce][,content_type])

      • 使用模版和一個戈丁的上下文環境,返回一個渲染后的HttpResponse對象
      • request: django的傳入請求
      • templater_name : 模版名稱
      • content_instance : 上下文環境
      • 參見例子: teacher_app/views/render_test
    • render_to_response

      • 根據給定的上下文字典渲染給定模版,返回渲染后的HttpResponse
      • 參見例子: teacher_app/views/render4_test
  • 系統內建視圖

    • 系統內建視圖,可以直接使用:
    • 404
      • default.page_not_found(request, template_name = '404.html')
      • 系統引發Http404時觸發
      • 默認窗體request_path變量給模版,即導致錯誤的URL
      • DEBUG = True則不會調用404, 取而代之是調試信息
      • 404視圖會被傳遞到一個RequestContext帝鄉寧切可以訪問模版上下文處理器提供的變量.
    • 500
      • default.server_error
      • DEBUG = True 不觸發
    • 403
      • default.permission_denied
      • DEBUG = True 不觸發
    • 500
      • default.bad_request
      • DEBUG = True 不觸發

Models 模型 (ORM)

  • ORM
    • Object Relation Map(對象關系映射) : 把面向對象思想轉換成關系數據庫思想.操作上把類等價于表格
    • 類對應表格
    • 類中的屬性對應表中的字段
    • 在應用中的models.py文件中定義class
    • 所有需要使用ORM的class都必須是 models.Model 的子類
    • class中的所有屬性對應表格中的字段
    • 字段的類型都必須使用 models.xxx 不能使用python中的類型
    • 在django種,Models負責跟數據庫交互


      ORM.png

Django 鏈接數據庫

  • 自帶默認數據庫Sqllite3
    • 關系型數據庫
    • 輕量級
    • 建議開發用sqlite3, 部署用mysql之類數據庫
    • 切換數據庫在settings中進行設置
    • 用django 連接 mysql

      DATABASES = [
          'default' = {
              'ENGINE' : 'django.db.backends.mysql',
              'NAME' : '數據庫名',
              'PASSWORD' : '數據庫密碼',
              'HOST' : '127.0.0.1', 
              'PORT' : '3306',
          }
      ]
      
    • django 連接 mysql需要在項目文件下的init文件中導入pymysql包
      • import pymysql
      • pymysql.install_as_MySQLdb()

models類的創建與使用

  • 定義和數據庫表映射的類

    • 在應用中的models.py文件中定義class [每一個app下面都有這個文件]
    • 所有需要使用ORM的class都必須是 models.Model 的子類
    • class中的所有屬性對應表格中的字段
    • 字段的類型都必須使用 modles.xxx 不能使用python中的類型
  • 字段常用參數

    • max_length : 規定數值的最大長度
    • blank : 是否允許字段為空,默認不允許
    • null : 在DB中控制是否保存為null, 默認為false
    • default : 默認值
    • unique : 唯一
    • verbose_name : 假名
  • 數據庫的遷移(在models里創建類后通知數據庫)

    • 在命令行中,生成數據遷移的語句(生成sql語句)
    • python manage.py makemigrations
    • 在命令行中,輸入數據遷移的指令
    • python manage.py migrate
    • 如果遷移中沒有變化或者報錯,可以強制遷移
    • python manage.py makemigrations 應用名
    • python manage.py migrate 應用名
    • 對于默認數據庫,為了避免出現混亂,前提是數據庫中沒有數據,可以刪除自定義app下的migrations文件夾和db.sqlites3數據庫
    • 如果報錯,顯示"App 'APP名字' could not be found. Is it in INSTALLED_APPS?", 說明沒有在settings.py里注冊:
        INSTALLED_APPS = (
            'django.contrib.admin',
            'django.contrib.auth',
            'django.contrib.contenttypes',
            'django.contrib.sessions',
            'django.contrib.messages',
            'django.contrib.staticfiles',
            'teacher', # 把自定義的app填進去
            'orm',
        )
    

查看數據庫中的數據

  • 1.啟動命令行:python manage.py shell
    注意點:對orm的操作分為靜態函數和非靜態函數兩種,靜態函數是指在內存中類共用的,非靜態函數是指每個實例掌握的
  • 2.在命令行中導入對應的映射類
  • from app名.models import 類名
  • 一個完整的例子:
        from teacher.models import Teacher
        dana = Teacher()
        dana.name = "Dana"
        dana.age = 18
        dana.address = "北京圖靈學院"
        dana.save() # 保存
        ta = Teacher.objects.all() # 返回集合
        ta[0].name # 訪問name屬性,顯示: Dana
        ta[0].age  # 訪問age屬性,顯示: 18
        ta[0].address # 訪問address屬性,顯示: '北京圖靈學院'
        ta[0].course # 訪問course屬性,顯示為空
  • 如上操作向Teacher表中增加幾條記錄之后,用for循環遍歷:
        for t in ta:
            print("Name: {0}, Age{1},Address:{2},Course:{3}".format(t.name,t.age,t.address,t.course))
        顯示結果:
          Name: Dana, Age18,Address:北京圖靈學院,Course:
          Name: Daozhang, Age45,Address:程度小北路,Course:
          Name: WangGonh, Age29,Address:,Course:Java
  • 查詢age=45的記錄
  • ta = Teacher.objects.filter(age=45)
  • ta <BR>
    直接輸入ta回車,顯示ta的內容,age=45的記錄只有一個就是daozhang, 顯示為:<BR>[<Teacher: Daozhang>]
  • 3.使用object屬性操作數據庫,object是模型中實際和數據進行交互的
  • 4.查詢命令
    • 類名.objects.all()查詢數據庫表中的所有內容,返回的結果是一個QuerySet查詢集合類型
    • 類名.object.filter(條件)
    • 常見查找方法
      1. 通用查找格式:屬性名__條件符號=值
    • 例如, 查找所有age大于18的記錄:
      ta = Teacher.objects.filter(age__gt > 18)
    • 條件符號有:
      • gt:大于
      • gte:大于等于
      • lt:小于
      • lte:小于等于
      • range:范圍
      • year:年份
      • isnull:是否為空
      • 2、查找等于指定值的格式:屬性名=值
      • 3、模糊查找:屬性名__查找方式=值
      • 查找course中包含字母T的老師<BR>
        ta = Teacher.objects.filter(course__contains = "T")
      • 查找方式有:
        • exact:精確等于
        • iexact:不區分大小寫
        • contains:包含
        • startwith:以..開頭
        • endwith:以..結尾

數據庫表關系

  • 多表聯查:利用多個多聯合查找某一項信息或者多項信息
    • 1:1 OneToOne

      • 建立關系:在模型任意一邊即可,使用OneToOneField
      • add: (增)有兩種方式:
        1. 實例化方法,直接實例化保存
        2. create方法,返回類型是<class 'rlt.models.Manager'>,推薦這種方法
        • PS: 添加有關系的一邊,使用create方法,或者使用實例創建
        • 例如:
           s = School()
           s.school_id = 2
           s.school_name = "nanjingtulingxueyuan"
           s.save()
           #方法1:直接實例化
           m =Manager()
           m.manager_id=10
           m.manager_name = "dana"
           m.my_school=s
           m.save()
           #方法2:使用create
           m = Manager.objects.create(manager_id=20,manager_name="erna",my_school=s)`
          
      • query: (查)
        • 由子表查母表(定義關系的表叫子表),由子表的屬性直接提取信息:
          m = Manager.objects.get(manager_name="dana")
          m
          <Manager: dana>
          m.my_school
          <School: nanjing tulingxueyuan>
          m.my_school.school_name
          'nanjing tulingxueyuan' # 查詢成功
          
        • 又或者可以把上述操作串起來一次性操作:
          Manager.objects.get(manager_name="dana").my_school.school_name
          'nanjing tulingxueyuan' # 查詢成功
          
        • 由母表查子表,使用雙下劃線:
          s = School.objects.get(manager__manager_name="dana")
          s
          <School: nanjing tulingxueyuan> # 查詢成功
          
      • change:(改)
        • 單個修改后使用save保存
          s.school_name = "南京圖靈學院"
          s.save()
          s
          <School: 南京圖靈學院> # 修改成功
          
        • 批量修改使用update
          ss = School.objects.all()
          ss.update(school_name="圖靈學院")
          ss
          [<School: 圖靈學院>, <School: 圖靈學院>] # 批量修改成功
          
        • 無論是對子表還是母表修改方法都一樣
      • delete:直接使用delete刪除
    • 1:N OneToMany

      • 一個表格的一個數據項/對象等,可有很多個另一個表格的數據項
      • 比如,一個學校可有很多個老師,一般一個老師只會在一個學校上課
      • 使用上
        • 使用ForeignKey
        • 在多的那一邊,比如上面的例子就是在Teacher表格里進行定義
      • add: (增)
        • 跟一對一方法類似,通過cerate和new來添加
        • create:把屬性都填滿,然后不需要手動保存
        • new(也就是實例化方法):可以屬性或者參數為空,必須用save保存
      • query:
        • 以學校和老師舉例
        • 如果知道老師,查學校,則通過增加的關系屬性,直接使用
        • 例如:查找t1老師是哪個學校的:
          t1.teacher_name
          '劉大拿'
          t1.my_school
          <School: 圖靈學院>
          
      • 反查
        • 由學校,想查下這個學校所有老師,則在學校后跟老師這個類(類名稱小寫)接下劃線set來表示
        • 可以簡單理解成teacher_set是School類里的一個隱藏屬性
        • 例如,查詢1號學校下面有多少個老師:
          ts = s1.teacher_set.all()
          ts
          [<Teacher: Teacher object>, <Teacher: Teacher object>]
          ts[0].teacher_name
          '劉大拿'
          
        • 又或者精確查找:
          t = s1.teacher_set.all().filter(teacher_name="劉大拿")
          t[0].teacher_name
          '劉大拿'
          
    • N:N ManyToMany

      • 表示任意一個表的數據可以擁有對方表格多項數據,反之亦然
      • 比如典型例子就是老師和學生,老師可以有多個學生,學生也可以有多個老師
      • 使用上,在任意一方,使用ManyToMany定義,只需要定義一邊
      • add:
        • 添加老師,則在Student實例.teachers.add(),也可以用create方法
          • 注意,用實例添加多對多數據,需要兩次save
          s1 = Student()
          s1.student_name = "aoteng"
          s1.save()
          t1 = Teacher.objects.all()[0]
          s1.teachers.add(t1)
          s1.save()
          t = s1.teachers.all()
          t[0].teacher_name
          '劉大拿'
          
      • query:
        • 跟一對多類似,使用隱含屬性set查詢
          t1 = Teacher.objects.all()[0]
          ss = t1.student_set.all() 
          ss[0].student_name
          'aoteng'
          
        • 注意:如果想實現雙向互查,必須在類代碼里面兩邊都相互添加一行:

          models.ManyToManyField
          s1 = Student.objects.all()[0] tt = s1.teacher_set.all() tt[0].teacher_name '劉大拿'

模版(Template)

  • 模板:一組相同或者相似的頁面,在需要個性化的地方進行留白,需要的時候只是用相應數據進行填充
    • 步驟
      1. 在settings.py中進行設置:TEMPLATES
      2. 在templates文件夾下編寫模板并調用
      一個最簡單的完整的例子:
      1. 激活環境: activate tl_django
      2. 創建項目: django-admin startproject django_tpl
      3. 創建app: python manage.py startapp mytpl
      4. 在項目的根目錄下建立一個templates的目錄
      5. 在templates目錄下新建一個one.html文件,內容如下:
          <html>
          <body>
          <h1>Hello World!</h1>
          </body>
          </html>
      6. 編輯Django系統自帶的settings.py文件: 
          找到Templates下的DIR位置,修改為:
          'DIRS': [os.path.join(BASE_DIR, "templates")],
      7. 為manager.py添加啟動變量runserver (僅限Pycharm環境)
      8. 編輯Django系統自帶的urls.py:
          在頭部添加包引用:import mytpl.views as v 
          (如果這行Pycharm出紅線,就選File菜單的Invalidate Caches/Restart,
          重啟后鼠標單擊項目目錄,Mark Directory As -> Sources Root
          如果有很多個Sources Root(Root目錄的顏色不同),取消其他的,
          確保只有一個Root且必須是當前目錄)
          最后在下方依葫蘆畫瓢添加一個路由:url(r'^one/', v.one),
      9. 打開mytpl下的views.py
          在頭部添加包引用:from django.http import HttpResponse
          添加一個函數one:
          def one(request):
              return render(request,r"one.html")
      10. 運行manage.py
      11. 在瀏覽器輸入:127.0.0.1:8000/one
      

模板-變量

  • 變量的表示方法:{{var_name}}
  • 在系統調用模板的時候,會有相應的數據查找相應的變量名稱,如果找到,則填充也叫渲染,否則跳過
  • 參見例子:two.html

模板-標簽

  • for標簽:

    {% for .. in .. %}
      循環語句
     {% endfor %}
    
  • 參見例子:three.html,顯示班級成績

  • if標簽,用來判斷條件

        {% if 條件 %}
            條件成立執行語句
        {% elif 條件 %}
            條件成立執行語句
        {% else %}
            以上條件都不成立執行語句
        {% endif %}
    
  • 參見例子:four.html

csrf標簽,跨站請求偽造

  • 在提交表單的時候,表單頁面需要加上{% csrf_token %}
  • 參見例子five_get請求表單地址, five_post發送表單信息地址
  • 原理:
    1. 瀏覽器提交一個get請求到服務器,服務器返回一個帶csrf_token的form回瀏覽器
    2. 此時瀏覽器正常提交form,隱含提交了csrf_token
    3. 服務器驗證這個新提交上來的csrf_token是否剛才服務器自己生成的那個csrf_token?
    4. 如果csrf_token不一致,說明本次提交是偽造的
  • 在settings.py:
    • 'django.middleware.csrf.CsrfViewMiddleware', 是控制csrf_token的開關,
    • 如果此選項關閉,則不對csrf_token進行檢查,反之則一定會檢查,如果打開了此設置但是在html代碼里又不含{% csrf_token %},則將報錯: CSRF token missing or incorrect.

SESSION

  • 為了應對HTTP的無協議性
  • 用來保存用戶比較敏感的信息
  • 他是屬于request的一個屬性
  • 常用操作:
    • request.session.get(key,defaultValue)
    • request.session.clear():清除全部
    • request.session[key] = value : 賦值
    • request.session.flush() : 刪除當前會話并清除會話的cookie
    • del request.session[key]

分頁

  • django提供現成的分頁器用來對結果進行分頁
  • from django.core.paginator import Paginator

Ajax

8. 基于類的視圖

  • 和基于函數的視圖的優勢和區別:
    • http方法的methode可以有各自的方法,不需要使用條件分支來解決
    • 可以使用OOP技術(例如Mixin)
  • 概述
    • 核心是允許使用不同的實例方法來響應不同的HTTP請求方法,而避開條件分支實現
    • as_view函數作為類的可調用入庫,該方法創建一個實例并調用dispatch方法,按照請求方法對請求進行分發,如果該方法沒有定義,則引發HttpResponseNotAllowed
  • 類屬性使用
    • 在類定義時直接覆蓋
    • 在調用as_view的時候直接作為參數使用,例如:
      urlpatterns = [
          url(r'^about/', GreetingView.as_view(greeting="Greetxxx")),
          ]
      
  • 對基于類的視圖的擴充大致有三種方法: Mixin, 裝飾as_view, 裝飾dispatch
    • 使用Mixin
      • 多繼承的一種形式,來自弗雷的行為和屬性組合在一起
      • 解決多繼承問題
      • View的子類只能單繼承,多繼承會導致不可期問題
    • 多繼承帶來的問題:
      • 結構復雜
      • 優先順序模糊
      • 功能沖突
    • 解決方法
      • 規格繼承 # java interface
      • 實現繼承 # python,ruby
  • 在URLconf中裝飾
    from django.contrib.auth.decorators import login_required, permission_required
    from django.views.generic import TemplateView
    from .views import VoteView
    urlpatterns = [
        url(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
        url(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
    ]
  • 裝飾類
    • 類的方法和獨立方法不同,不能直接運用裝飾器,需要用methode_decorator進行裝飾
         from django.contrib.auth.decorators import login_required
         from django.utils.decorators import method_decorator
         from django.views.generic import TemplateView
         class ProtectedView(TemplateView):
             template_name = 'secret.html'
             @method_decorator(login_required)
             def dispatch(self, *args, **kwargs):
             return super(ProtectedView, self).dispatch(*args, **kwargs)
    

Admin管理模塊 (可以理解為Django自帶的可定制型phpMyAdmin)

  • 首先進行數據遷移,然后創建一個超管帳號
    python manage.py makemigrations
    python manage.py migrate
    python manage.py createsuperuser
    
  • settings.py里面改為漢語:
    LANGUAGE_CODE ='zh-Hans' #'en-us'
    TIME_ZONE = 'Asia/Shanghai' #'UTC'
    
  • 最后在瀏覽器輸入:127.0.0.1/admin
  • 進入管理界面后,只有一個空的項目和User和Group表可以管理,
  • 在模型建立完畢后,界面會增加很多內容,可以設置各個模型(也就是數據庫的表,這里稱為模型)
  • 先在models.py里建立3個模型:ClassRoom、Teacher、Student
from django.db import models

# Create your models here.
class ClassRoom(models.Model):
    roomID= models.IntegerField()
    loc = models.CharField(max_length=20)
    roomName = models.CharField(max_length=20)
    def __str__(self):
        return self.roomName

class Teacher(models.Model):
    name = models.CharField(max_length=5)
    course = models.CharField(max_length=20)
    room = models.OneToOneField(ClassRoom)
    def __str__(self):
        return self.name

class Student(models.Model):
    name = models.CharField(max_length=20)
    age = models.IntegerField()
    room = models.ForeignKey(ClassRoom)
    def __str__(self):
        return self.name
  • 記得模型建立后,還需要進行一次完整的數據遷移才會真正在數據庫中建表

2. 綁定管理模型

  • 在app目錄下修改admin.py:
    admin.site.register(Student, StudentAdminInfo)
    admin.site.register(ClassRoom, ClassRoomAdminInfo)
    admin.site.register(Teacher, TeacherAdminInfo)
    

3. 設置admin管理類

  • 實現方式(包括顯示、增、刪、改都集成在里面了)

    • ModelAdmin
    • 在admin.py里為每個模型添加管理類:
      class ClassRoomAdminInfo(admin.ModelAdmin):
          pass
      
      class TeacherAdminInfo(admin.ModelAdmin):
          pass
      
      class StudentAdminInfo(admin.ModelAdmin):
          pass
      
    • 裝飾器
  • list_per_page : 修改頁面顯示數量:

  • actions_on_top/buttom :操作選項在屏幕上方還是下方

  • list_display=[] : 控制列表中顯示的內容:

  • 以上設置都在admin.py的管理類里面修改:

    class TeacherAdminInfo(admin.ModelAdmin):
        list_per_page = 2 
        actions_on_top = False
        actions_on_bottom = True
        list_display = ["name","room"]
    
  • 除了顯示字段外,還可以將方法作為列顯示:

    • 函數必須有返回值
    • short_description : 設置作為顯示內容
    • admin_order_field : 排序綁定
    • PS:默認情況下,點擊列的標題,可以以列為依據排序,但是以方法作為列是不能排序的,<BR>
      這種情況下也可以為它綁定一個列,起到排序的功能
    • 在Teacher類里面加入以下代碼:
      # 定義一個方法,這個方法可以作為列顯示
      def curTime(self):
          return  time.time()
      
      curTime.short_description = "當前時間" # 如果不設此行,默認顯示為類名curTime
      curTime.admin_order_field = "name" # 以字段名name為排序依據
      
  • 關聯對象(多表顯示)

    • 使用方法
    • 在Teacher類里面加入以下代碼:
    def getRoomName(self):
        return self.room.roomName # 因為Teacher和ClassRoom是一對一關系,因此Teacher里可以訪問ClassRoom的字段
    getRoomName.short_description = "教室"
    
  • 搜索功能 (search_fields)

    • 在admin.py文件的TeacherAdminInfo里面增加:
    search_fields = ["name"] # 搜索 name 列
    
    • 界面將會出現一個搜索框,并以name列為條件搜索
  • 字段屏蔽 - fields

    • 默認情況下,字段是全部顯示的,但是,也可以屏蔽
    • 同樣的,在TeacherAdminInfo里面增加:
    fields = ["name","course"] # 只顯示name和course,屏蔽了Room
    
  • 分組設置 - fieldsets

    • 為了方便管理和讓顯示效果更好,字段也可以分組:
    • 在TeacherAdminInfo里面增加元組fieldsets:
    # fields = ["name", "course"]
    fieldsets = (
        ("基本信息", {"fields": ["name", ]}),
        ("其他信息", {"fields": ["room", "course"]}),
    
    )
    
    • 特別注意:fields和fieldsets不能共存,否則報錯。
  • 其他設置 - admin.site

    • 在admin.site下有許多設置,可以控制站點信息
    admin.site.site_header = "這是站頭"
    admin.site.site_title = "這是站標題"
    admin.site.index_title = "這是首頁標語"
    
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。