Python筆記整理 - Django

Django Reinhardt.jpg

Django 系統(tǒng)

環(huán)境搭建

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

后臺流程

Django.png

創(chuàng)建第一個Django程序

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

命令行啟動:

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

PyCharm啟動

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

路由系統(tǒng) - urls

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


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

2. 正常映射

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

3.URL 中帶參數(shù)映射

  • 在多事件處理代碼中需要由URL傳入?yún)?shù),形如/myurl/param中的param

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

  • 統(tǒng)稱的形式如下:

    /search/page/432 中的432需要經(jīng)常性變化內(nèi)容,就是參數(shù)

  • 一個較為復(fù)雜的例子:

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

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

4. URL在APP中處理

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

5. URL中嵌套參數(shù)

  • 捕獲某個參數(shù)的一部分
  • 例如URL /index/page-3 , 需要捕獲數(shù)字3作為參數(shù)
    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)
    • 以上就是指從一個參數(shù)中再提煉一個參數(shù)(我個人認(rèn)為第三個正則更簡單明了一些)

6. 傳遞額外的參數(shù)

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

7.URL的反向解析 reverse

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

VIEWS 視圖

1. 視圖概述

  • 視圖即視圖函數(shù),接受WEB請求返回WEB相應(yīng)的事務(wù)處理函數(shù).
  • 響應(yīng)指符合http協(xié)議要求的任何內(nèi)容,包括json, string, html等
  • 本章忽略事務(wù)處理, 重點在如何返回處理結(jié)果上

2. 其他簡單視圖

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

3. HttpResponse詳解

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

4. HttpRespnseRedirect

  • 重定向, 服務(wù)器端跳轉(zhuǎn)
  • 構(gòu)造函數(shù)的第一個參數(shù)用來指定重定向的地址
  • 例子: ShowViews/views.py
  • 在east/urls中添加以下內(nèi)容:
            url(r'^v10_1/', views.v10_1),
            url(r'^v10_2/', views.v10_2),
            url(r'^v11/"' views.v11, name = "v11"),
            
           # /east/ShowViews/views 中添加以下內(nèi)容
           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介紹

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

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

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

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

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

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

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

  • 手動編寫視圖

    • 實驗?zāi)康?

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

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

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

    • 分析:

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

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

      • 根據(jù)給定的上下文字典渲染給定模版,返回渲染后的HttpResponse
      • 參見例子: teacher_app/views/render4_test
  • 系統(tǒng)內(nèi)建視圖

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

Models 模型 (ORM)

  • ORM
    • Object Relation Map(對象關(guān)系映射) : 把面向?qū)ο笏枷朕D(zhuǎn)換成關(guān)系數(shù)據(jù)庫思想.操作上把類等價于表格
    • 類對應(yīng)表格
    • 類中的屬性對應(yīng)表中的字段
    • 在應(yīng)用中的models.py文件中定義class
    • 所有需要使用ORM的class都必須是 models.Model 的子類
    • class中的所有屬性對應(yīng)表格中的字段
    • 字段的類型都必須使用 models.xxx 不能使用python中的類型
    • 在django種,Models負(fù)責(zé)跟數(shù)據(jù)庫交互


      ORM.png

Django 鏈接數(shù)據(jù)庫

  • 自帶默認(rèn)數(shù)據(jù)庫Sqllite3
    • 關(guān)系型數(shù)據(jù)庫
    • 輕量級
    • 建議開發(fā)用sqlite3, 部署用mysql之類數(shù)據(jù)庫
    • 切換數(shù)據(jù)庫在settings中進行設(shè)置
    • 用django 連接 mysql

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

models類的創(chuàng)建與使用

  • 定義和數(shù)據(jù)庫表映射的類

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

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

    • 在命令行中,生成數(shù)據(jù)遷移的語句(生成sql語句)
    • python manage.py makemigrations
    • 在命令行中,輸入數(shù)據(jù)遷移的指令
    • python manage.py migrate
    • 如果遷移中沒有變化或者報錯,可以強制遷移
    • python manage.py makemigrations 應(yīng)用名
    • python manage.py migrate 應(yīng)用名
    • 對于默認(rèn)數(shù)據(jù)庫,為了避免出現(xiàn)混亂,前提是數(shù)據(jù)庫中沒有數(shù)據(jù),可以刪除自定義app下的migrations文件夾和db.sqlites3數(shù)據(jù)庫
    • 如果報錯,顯示"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',
        )
    

查看數(shù)據(jù)庫中的數(shù)據(jù)

  • 1.啟動命令行:python manage.py shell
    注意點:對orm的操作分為靜態(tài)函數(shù)和非靜態(tài)函數(shù)兩種,靜態(tài)函數(shù)是指在內(nèi)存中類共用的,非靜態(tài)函數(shù)是指每個實例掌握的
  • 2.在命令行中導(dǎo)入對應(yīng)的映射類
  • from app名.models import 類名
  • 一個完整的例子:
        from teacher.models import Teacher
        dana = Teacher()
        dana.name = "Dana"
        dana.age = 18
        dana.address = "北京圖靈學(xué)院"
        dana.save() # 保存
        ta = Teacher.objects.all() # 返回集合
        ta[0].name # 訪問name屬性,顯示: Dana
        ta[0].age  # 訪問age屬性,顯示: 18
        ta[0].address # 訪問address屬性,顯示: '北京圖靈學(xué)院'
        ta[0].course # 訪問course屬性,顯示為空
  • 如上操作向Teacher表中增加幾條記錄之后,用for循環(huán)遍歷:
        for t in ta:
            print("Name: {0}, Age{1},Address:{2},Course:{3}".format(t.name,t.age,t.address,t.course))
        顯示結(jié)果:
          Name: Dana, Age18,Address:北京圖靈學(xué)院,Course:
          Name: Daozhang, Age45,Address:程度小北路,Course:
          Name: WangGonh, Age29,Address:,Course:Java
  • 查詢age=45的記錄
  • ta = Teacher.objects.filter(age=45)
  • ta <BR>
    直接輸入ta回車,顯示ta的內(nèi)容,age=45的記錄只有一個就是daozhang, 顯示為:<BR>[<Teacher: Daozhang>]
  • 3.使用object屬性操作數(shù)據(jù)庫,object是模型中實際和數(shù)據(jù)進行交互的
  • 4.查詢命令
    • 類名.objects.all()查詢數(shù)據(jù)庫表中的所有內(nèi)容,返回的結(jié)果是一個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:不區(qū)分大小寫
        • contains:包含
        • startwith:以..開頭
        • endwith:以..結(jié)尾

數(shù)據(jù)庫表關(guān)系

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

      • 建立關(guān)系:在模型任意一邊即可,使用OneToOneField
      • add: (增)有兩種方式:
        1. 實例化方法,直接實例化保存
        2. create方法,返回類型是<class 'rlt.models.Manager'>,推薦這種方法
        • PS: 添加有關(guān)系的一邊,使用create方法,或者使用實例創(chuàng)建
        • 例如:
           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: (查)
        • 由子表查母表(定義關(guān)系的表叫子表),由子表的屬性直接提取信息:
          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 = "南京圖靈學(xué)院"
          s.save()
          s
          <School: 南京圖靈學(xué)院> # 修改成功
          
        • 批量修改使用update
          ss = School.objects.all()
          ss.update(school_name="圖靈學(xué)院")
          ss
          [<School: 圖靈學(xué)院>, <School: 圖靈學(xué)院>] # 批量修改成功
          
        • 無論是對子表還是母表修改方法都一樣
      • delete:直接使用delete刪除
    • 1:N OneToMany

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

      • 表示任意一個表的數(shù)據(jù)可以擁有對方表格多項數(shù)據(jù),反之亦然
      • 比如典型例子就是老師和學(xué)生,老師可以有多個學(xué)生,學(xué)生也可以有多個老師
      • 使用上,在任意一方,使用ManyToMany定義,只需要定義一邊
      • add:
        • 添加老師,則在Student實例.teachers.add(),也可以用create方法
          • 注意,用實例添加多對多數(shù)據(jù),需要兩次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'
          
        • 注意:如果想實現(xiàn)雙向互查,必須在類代碼里面兩邊都相互添加一行:

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

模版(Template)

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

模板-變量

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

模板-標(biāo)簽

  • for標(biāo)簽:

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

  • if標(biāo)簽,用來判斷條件

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

csrf標(biāo)簽,跨站請求偽造

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

SESSION

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

分頁

  • django提供現(xiàn)成的分頁器用來對結(jié)果進行分頁
  • from django.core.paginator import Paginator

Ajax

8. 基于類的視圖

  • 和基于函數(shù)的視圖的優(yōu)勢和區(qū)別:
    • http方法的methode可以有各自的方法,不需要使用條件分支來解決
    • 可以使用OOP技術(shù)(例如Mixin)
  • 概述
    • 核心是允許使用不同的實例方法來響應(yīng)不同的HTTP請求方法,而避開條件分支實現(xiàn)
    • as_view函數(shù)作為類的可調(diào)用入庫,該方法創(chuàng)建一個實例并調(diào)用dispatch方法,按照請求方法對請求進行分發(fā),如果該方法沒有定義,則引發(fā)HttpResponseNotAllowed
  • 類屬性使用
    • 在類定義時直接覆蓋
    • 在調(diào)用as_view的時候直接作為參數(shù)使用,例如:
      urlpatterns = [
          url(r'^about/', GreetingView.as_view(greeting="Greetxxx")),
          ]
      
  • 對基于類的視圖的擴充大致有三種方法: Mixin, 裝飾as_view, 裝飾dispatch
    • 使用Mixin
      • 多繼承的一種形式,來自弗雷的行為和屬性組合在一起
      • 解決多繼承問題
      • View的子類只能單繼承,多繼承會導(dǎo)致不可期問題
    • 多繼承帶來的問題:
      • 結(jié)構(gòu)復(fù)雜
      • 優(yōu)先順序模糊
      • 功能沖突
    • 解決方法
      • 規(guī)格繼承 # java interface
      • 實現(xiàn)繼承 # 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)

  • 首先進行數(shù)據(jù)遷移,然后創(chuàng)建一個超管帳號
    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表可以管理,
  • 在模型建立完畢后,界面會增加很多內(nèi)容,可以設(shè)置各個模型(也就是數(shù)據(jù)庫的表,這里稱為模型)
  • 先在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
  • 記得模型建立后,還需要進行一次完整的數(shù)據(jù)遷移才會真正在數(shù)據(jù)庫中建表

2. 綁定管理模型

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

3. 設(shè)置admin管理類

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

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

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

  • list_display=[] : 控制列表中顯示的內(nèi)容:

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

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

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

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

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

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

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

    • 在admin.site下有許多設(shè)置,可以控制站點信息
    admin.site.site_header = "這是站頭"
    admin.site.site_title = "這是站標(biāo)題"
    admin.site.index_title = "這是首頁標(biāo)語"
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容