Django框架學習

Django是如今世界上python語言應用最普遍、發展最成熟的web框架。它足夠完整 ,不須要依賴其餘就能夠開發出 很是完整的web應用。Django的主要內容以下:html

  • Django綜述:瞭解Django的歷史,特色,整體結構,而且實踐在主機中安裝Django框架。
  • 開發Django站點:經過實際的例子瞭解Django站點的開發流程。
  • Django模型層:系統學習models層組件及其開發技巧。
  •  Django視圖層:詳細的URL定製方法,裝飾器的開發和使用。
  • Django表單:系統學習Django表單的開發方法,經常使用的字段類型。
  • 管理員站點:學習配置和開發Django自帶的管理員站點組件,快速創建管理界面

 

一.Django綜述

1. Django的特色和結構

Django於2003年誕生於美國的堪薩斯州,最初是用來製做在線新聞web網站,於2005年加入了BSD許可證家族,成爲開源網絡框架。Django根據比利時的爵士音樂家Django Reinhardt命名。前端

1.1 Django框架的特色

相對於python的其它web框架,Django的功能是最完整的,Django定義了服務發佈,路由映射,模板編程,數據處理的一整套功能。這也意味着Django模塊之間緊密耦合,開發者須要學習Django本身定義的一整套技術。它的主要特色以下:java

  •  最完善的文檔。
  • 集成數據訪問組件:Django的Models層自帶數據庫ORM組件,似的開發者無需學習其餘的數據庫訪問技術(DBI,SQLAlchemy)
  • 強大的URL映射技術:Django使用正則表達式管理URL映射,所以給開發者帶來了極高的靈活性。
  • 後臺管理系統的自動生成:開發者只須要經過簡單的幾行配置和代碼就能夠實現完整的後臺數據管理web控制檯。
  • 錯誤信息很是完整:開發調試過程當中出現錯誤,Django能夠提供很是完整的錯誤信息幫助開發者定位問題,不如缺乏xxx組件的配置引用等。

1.2 Django的組成結構

Django是遵循MVC架構的web開發框架,主要又如下幾個部分組成。python

  • 管理工具:一套內置的建立站點,遷移數據,維護靜態文件的命令工具。
  • 模型(Model):提供數據訪問接口和模塊,包括數據字段、元數據、數據關係等的定義和操做。
  • 視圖(View):Django的視圖層封裝了HTTP Response和request的一系列操做和數據流,主要的功能包括URL映射機制、綁定模板等。
  • 模板(Templates):是一套Django本身的頁面渲染模板語言,用若干內置的tags和filters定義頁面的生成方式。
  • 表單(form):經過內置的數據類型和控件生成HTML表單。
  • 管理站點(Admin):經過聲明須要管理的Model,快速生成後臺數據管理站點。

 

1.3 安裝Django

在安裝pip工具的python環境中能夠直接使用pip install django命令進行安裝。或者下載Django的離線包,使用python setup.py install命令進行安裝。mysql

安裝完成後,進入python,經過以下命令測試是否安裝成功。git

import djangoweb

print(django.version)正則表達式

 

二.Django項目站點

2.1 創建項目

在進行項目開發的第一步就是要創建Django項目,創建的語法以下:sql

django-admin startproject djangotest。數據庫

上述代碼中的django-admin是安裝好Django組件後在python目錄中生成的Django項目管理工具。該命令在當前的目錄下建立了項目工程文件,工程文件中的目錄結構以下:

 

上圖就是成功生成的項目文件,默認生成的幾個文件很是重要,在從此的開發或者維護中要一直使用它們。各個文件簡單的解釋以下:

  • manage.py:django用於管理項目的命令行工具,其中的站點開啓,數據庫生成。遷移,靜態文件設置等都要經過該文件完成。
  • 內置的djangotest/目錄中包括的是項目的實際文件,同時包含了一個__init__.py文件,故該目錄是一個python包。
  • setting.py文件:django項目的配置文件,其中定義了django的組件、項目名稱、數據庫鏈接參數以及其餘的python包信息。
  • urls.py:維護項目的URL映射。
  • wsgi.py:定義WSGI的接口信息,用於與其餘的web服務器進行交互,通常不須要進行改動。

2.2 創建應用

爲了在項目中開發符合MVC架構的實際應用程序,咱們須要在項目中創建Django應用。每個django項目能夠包含多個django應用。應用的創建語法以下。

python manage.py startapp app。

其中的manage.py是創建項目是用到的命令行工具,startapp是命令行關鍵字,app是創建的應用名稱。命令完成後會在項目的目錄下創建以下圖所示的文件結構。

 

 

其中各個文件功能的說明以下:

  • __init__.py:暫無內容,只是聲明app是一個python包。
  • admin.py:管理站點模型的的聲明文件,默認狀況下什麼東西都莫得。
  • apps.py:應用信息的定義文件。在其中生成了AppConfig,該類用於定義應用名等Meta數據。
  • migrations包:遷移數據時生成的中間文件放在該目錄下。
  • models.py:添加模型層數據類的文件。
  • test.py:測試代碼文件。
  • views.py:定義URL響應函數,業務代碼的具體實現。

2.3 基本視圖

在完成django項目和應用的創建後,就能夠開始編寫網站的代碼了,下面簡單演示一下django的路由映射功能。

(1)在app/views.py中建立一個路由響應函數,代碼以下

from django.http import HttpResponse

def welcome(request):
    return HttpResponse('<h1>你好,django</h1>')

(2)接下來,要經過URL映射將用戶的HTTP訪問和該函數綁定起來,在app/目錄下建立一個urls.py文件,其文件的內容以下:

from django.contrib import adminfrom django.conf.urls import url
from .apps import views

urlpatterns = [
    url(r'',views.welcome),
    #url(r'',views.welcome),
]

(3)在項目djangotest/urls.py文件中的urlpatterns中新增長一項,聲明對應用app中的urls.py文件的引用,具體代碼以下

from django.contrib import admin
from django.urls import url
from django.conf.urls import include

urlpatterns = [
    url('admin/', admin.site.urls),
url(r'app/', include('app.urls')),
]
首先導入django.conf.urls.include()函數,以後再urlpatterns列表中增長一個路徑app/,將其轉接到app.urls包,這樣經過include()函數就能夠將2個urlpatterns鏈接起來。
(4)上述代碼書寫完成後,輸入python manage.py runserver  127.0.0.0:8888。命令開啓web服務,在瀏覽其中輸入網址http://127.0.0.0:8888/app,結果以下圖所示。

 

 

2.4 模型類

這一節介紹的是Model層的處理,設計和開發信息發佈的數據訪問層。

2.4.1 配置項目INSTALLED_APPS

要在django項目的setting.py文件中告訴django須要安裝應用app中的模型,方法是在setting.py文件中的INSTALLED_APPS數據結構中,在其中添加應用app的 config類,代碼以下:

INSTALLED_APPS = [
 'app',   # 新增
]

2.4.2 模型定義

打開app/models.py文件,在其中新建一個模型類Mount,用來定義信息發佈表,代碼以下:

from django.db import models

class Mount(models.Model):
    content = models.CharField(max_length=200)
    username = models.CharField(max_length=20)
    kind = models.CharField(max_length=20)

首先引入modoels類,全部的django模型類都是繼承於它。類Mount繼承了models類,在其中定義了3個字段content:消息的內容、username:發佈人名稱、kind:消息的類型。

2.4.3 生成數據遷移文件

django的術語「生成數據移植文件」是指將models.py中定義的數據錶轉換成數據庫生成腳本的過程。該過程經過命令行工具manage.py完成,具體的命令輸出以下:

 

經過輸出咱們能夠看到完成了模型Mount的創建。輸出中的0001_initial.py是數據庫生成的中間文件,經過它能夠知道當前數據庫的版本;該文件以及之後全部的migration文件都存儲於目錄migrations/中。

同時在makemigrations的過程當中,django會對比models.py中模型和已有數據庫之間的差別,沒有差別則不作操做,如再次執行makemigrations操做時將產生以下輸出:

 

可是若是對models.py文件做出修改時,則在下一次makemigrations的時候會將修改的內容同步到數據庫中。例如將kind字段修改成長度30後,執行操做,結果以下:

 

在該過程當中產生了新的中間文件0002_auto_20190526_1431.py。須要注意的是djangotest\app\migrations目錄中的文件都有manage.py本身維護,開發者不宜修改其中的內容。

2.4.4 移植到數據庫

在模型的修改過程當中能夠隨時調用makemigrations生成的中間移植文件。當須要真正的修改數據庫的時候,須要經過manage.py的migrate命令讓修改同步到數據庫。例如:

 

2.5 表單視圖

2.5.1 定義表單類

創建表單類文件djangotest/app/forms.py,在其中定義表單類MountForm,代碼以下:

from django.forms import ModelForm
from models import Mount

class MountForm(ModelForm):
  class Meta:
      model = Mount
      fields = '__all__'
  • 引入from django.forms import ModelForm類,該類是全部Django表單類的基類。解析以下:
  • 引入models.py文件中的Mount類,以便在之後進行關聯。
  • 定義表單類MountForm,在其中定義子類Meta。在子類中聲明與本表單關聯的模型類和字段。
  • Fields字段能夠設爲__all__,也能夠用列表的形式聲明所要導入的屬性,好比:fields = ('content','username','kind'),all是將全部字段導入。

2.5.2 修改模型類

爲了使用戶可以以單選的方式設置消息類型,則須要在models.py文件中定義單選的枚舉類型,而且與模型類Mount進行關聯。代碼以下:

from django.db import models

# Create your models here.
class Mount(models.Model):
  content = models.CharField(max_length=200)
  username = models.CharField(max_length=20,default='張曉琳')
  # 新增元祖用於設置消息枚舉類型
  KIND_CHOICES = (('python','python'),('java','java'),('C語言','C語言'),
                  ('C++', 'C++'),
                  ('mysql', 'mysql'),)
  kind = models.CharField(max_length=30,choices=KIND_CHOICES,default=KIND_CHOICES[0])
  • 爲kind字段增長了消息枚舉類型,爲username字段使用default增長了默認屬性。代碼解析:
  • 本次編輯使得模型層發生改變,須要進行同步數據庫的操做,具體操做參考2.4.3和2.4.4章節的內容。

2.5.3 開發模板文件

模板文件是python web框架中用於產生HTML、XML等文本格式文檔的術語。模板文件自己也是一種文本文件,開發者須要手工進行編輯。創建目錄djangotest/app/templates,在其中新建模板文件moments_input.html,文件內容以下:

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>消息錄入頁面</title>
  </head>
  <body>
  <form action="?" method="post">
    <fieldset>
        <legend>請輸入並提交</legend>
        {{ form.as_p }}
        <input type="submit" value="提交" />
    </fieldset>
  </form>
  </body>
  </html>

 模板文件是html文件,其中的模板內容使用大括號進行標識。這裏使用{{ form.as_p }}定義表單類的輸入字段。

2.5.4 開發視圖文件

接下來開發的是視圖文件,使得表單類和頁面模板可以銜接起來。打開djangotest/app/views.py文件,在其中加入以下函數:

import os
from app.form import MountForm
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
def moments_input(request):
    if request.method == 'POST':
        form = MountForm(request.POST)
        if form.is_valid():
            moment = form.save()
            moment.save()
            # return HttpResponseRedirect("app.views.welcome")
    else:
        form = MountForm()
    project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    return render(request,os.path.join(project_root,'app/templates'),'moments_input.html',{'form':form})

在urls.py文件中增長視圖函數的路由映射。

urlpatterns = [
    url('admin/', admin.site.urls),
    url(r'^app/', include('app.urls')),
]

訪問地址爲http://127.0.0.1:9999/app/moments_input

 

 

三.Django管理界面

站點分爲「內容發佈」和「公共訪問」兩部分,「內容發佈」的部分負責添加、修改、刪除內容,開發這些重複的功能是一件單調乏味、缺少創造力的工做。爲此,Django會根據定義的模型類徹底自動地生成管理模塊

3.1使用django的管理

3.1.1建立管理員用戶

  • 建立一個管理員用戶:python manage.py createsuperuser,按提示輸入用戶名、郵箱、密碼
  • 啓動服務器,經過「127.0.0.1:8000/admin」訪問,輸入上面建立的用戶名、密碼完成登陸
  • 進入管理站點,默承認以對groups、users進行管理

3.1.2管理界面本地化

編輯settings.py文件,設置編碼、時區

LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'

3.1.3向admin註冊booktest的模型

打開booktest/admin.py文件,註冊模型

from django.contrib import admin
from models import BookInfo
admin.site.register(BookInfo)

刷新管理頁面,能夠對BookInfo的數據進行增刪改查操做

問題:若是在str方法中返回中文,在修改和添加時會報ascii的錯誤

解決:在str()方法中,將字符串末尾添加「.encode('utf-8')」

3.1.4自定義管理頁面

Django提供了admin.ModelAdmin類

經過定義ModelAdmin的子類,來定義模型在Admin界面的顯示方式

class QuestionAdmin(admin.ModelAdmin):
    ...
admin.site.register(Question, QuestionAdmin)
列表頁屬性說明
  • list_display:顯示字段,能夠點擊列頭進行排序——list_display = ['pk', 'btitle', 'bpub_date']
  • list_filter:過濾字段,過濾框會出如今右側——list_filter = ['btitle']
  • search_fields:搜索字段,搜索框會出如今上側——search_fields = ['btitle']
  • list_per_page:分頁,分頁框會出如今下側——list_per_page = 10
添加、修改頁屬性
  • fields:屬性的前後順序——fields = ['bpub_date', 'btitle']
  • fieldsets:屬性分組
fieldsets = [
    ('basic',{'fields': ['btitle']}),
    ('more', {'fields': ['bpub_date']}),
]

3.2關聯對象

對於HeroInfo模型類,有兩種註冊方式

  • 方式一:與BookInfo模型類相同
  • 方式二:關聯註冊

按照BookInfor的註冊方式完成HeroInfo的註冊

接下來實現關聯註冊

from django.contrib import admin
from models import BookInfo,HeroInfo
 
class HeroInfoInline(admin.StackedInline):
    model = HeroInfo
    extra = 2
 
class BookInfoAdmin(admin.ModelAdmin):
    inlines = [HeroInfoInline]
 
admin.site.register(BookInfo, BookInfoAdmin)
能夠將內嵌的方式改成表格

class HeroInfoInline(admin.TabularInline)

3.2.1布爾值的顯示

發佈性別的顯示不是一個直觀的結果,可使用方法進行封裝

def gender(self):
    if self.hgender:
        return ''
    else:
        return ''
gender.short_description = '性別'
在admin註冊中使用gender代替hgender

class HeroInfoAdmin(admin.ModelAdmin):
    list_display = ['id', 'hname', 'gender', 'hcontent']

 

 

四.Django模型層

Django模型層是Django框架自定義的一套獨特的ORM技術,經過上幾章節的總結學習,咱們已經大概瞭解了Django模型層的基本概念和開發流程。如今來學習模型層的技術細節和高級話題。

4.1 模型類定義語法

使用Django模型開發的首要任務就是定義模型類和類的屬性。每一個模型類均可以被映射爲數據庫中的一個表,類屬性被映射成爲數據字段,除此以外,數據庫中的主鍵、外鍵、約束等也能夠經過類屬性完成定義。

4.1.1基本操做

模型定義的的基本結構以下所示:

from django.db import models

class ModelsName(models.Model):
    field1 = models.XXfield(...)
    field2 = models.XXfield(...)
    ...
    class Meta:
        db_table = ...
        other_metas = ...
  • 全部Django模型類繼承自django.db.models.Model類。解析以下:
  • 經過其中的類屬性定義模型字段,模型的字段屬性必須是某種models.XXField類型。
  • 經過模型類中的Meta子類定義模型元數據,好比數據庫表的名稱,數據默認的排序方式等。

4.1.2 子類Meta屬性彙總

屬性

屬性值

說明

abstract

True  or  False

標識本類是否爲抽象的基類

app_lable

app_lable = 「myapp」

定義本類所屬的應用

 

 

db_table

 

 

db_table=「mytable」

映射的數據庫表名稱

說明:若是Meta中不提供db_table字段,則django會爲模型自動生成數據庫表名,格式爲「應用名_模型名」。

 

db_tablespace

 

映射的表空間名稱。表空間的概念只在某些數據庫中如oracle中存在,不存在表空間概念的數據庫將會忽略本字段。

Default_related_name

定義本模型的反向關係引用名稱,默認和模型名一致。

 

 

get_latest_by

 

 

定義按那個字段值排列得到模型的開始或者結束記錄,本屬性值一般指向一個日期或者整形的模型字段。

 

 

managed

 

 

True  or  False

定義django的manage.py命令行工具是否管理本模型。屬性默認設置爲TRUE。設置爲false時,須要手動維護數據庫表。

order_with_respect_to

定義本模型能夠按照某種外鍵引用的關係排序。

 

ordering

Ordering = [「username」「-pub_data」]

本模型記錄的默認排序字段,能夠設置多個字段,默認爲升序排列。降序排列的話在字典前加上-

default_permissions

Add,change,delete

模型的操做權限,默認如值所示。

proxy

True  or  False

本模型及全部繼承自本模型的子類是否爲代理模式。

 

 

required_db_features

 

 

fequired_db_features

=[「gis_enabled」]

定義底層數據庫所必須具有的特性,如值所示只將本數據模型生成在知足gis_enabled特性的數據庫中

 

 

required_db_vendor

SQLite、PostgreSQL、MySQL、Oracle

定義底層數據庫的類型,若是定義了本屬性,則模型只能在其聲明的數據庫中維護。

 

unique_together

 

unique_together = ((「user」,「pwd」))

用來設置不重複的的字段組合,必須惟一(能夠將多個字段作聯合惟一)。

 

index_together

index_together=[

[「pun_data」,「deadline」]]

定義聯合索引的字段,能夠定義多個。

 

 

verbose_name

 

verbose_name = ‘資產管理’

定義一個易於理解和表述的單數形式的對象名稱。若是不設置該值,則Django將會使用該models的類名做爲它的對象表述名。

verbose_name_plural

 

定義一個易於理解和表述的複數形式的對象名稱。

 

4.1.3 經常使用字段類型

Django的普通字段是指模型類中除了外鍵之外的數據字段屬性。它爲Django使用模型的時候提供以下信息:

  • 在數據庫中用什麼類型定義模型字段,好比INTEGER、VARCHAR等。
  • 用什麼樣的HTML標籤顯示模型字段,好比<input type=」radio」>
  • 須要什麼樣的HTML表單驗證數據。

全部的數據字段的屬性必須繼承自抽象類django.db.models.Field,咱們能夠本身定義繼承自該類的數據字段,也可使用Django預約義的一系列數據字段,常見的Django預約義字段類型描述以下表所示。

字段

字段說明

 

 

AutoField

一個自動遞增的整形字段,添加記錄時它會自動增加。AutoField字段一般充當數據表的主鍵;若是沒有添加,django會自動添加一個該字段。

BigIntegerField

64位的整型字段

BinaryField

二進制數據字段,經過bytes進行賦值

BooleanField

布爾字段,對應<input type=「CheckBox」>

CharField

字符串字段,對應<input type=「text」>

TextField

大容量文本字段,對應<textarea>

CommaSeparatedIntegerField

存放逗號分隔的整數值,有特殊的表單驗證要求

 

 

DateField

日期字段,相對應的HTML標籤是<input type=「text」>、JavaScript日曆和一個today快捷按鍵。可選參數:auto_now:保存時,設置爲當前時間;auto_now_add:首次建立時,保存爲當前時間。

DateTimeField

相似於DateField,可是它卻支持時間的輸入。

DurationField

存儲時間週期,用python的timedelta類型構建。

EmailField

檢查Email合法性的CharField。

 

 

FileField

文件上傳字段。在定義本字段是必須傳入參數upload_to,用於保存上傳下載文件的服務器文件系統的路徑。這個路徑必須包含strftime formatting,該格式將被上載文件的date/time替換

FilePathField

按照目錄的規則限制選擇文件,定義本字段是必須傳入參數path,用以限定目錄。

FloatField

浮點型字段。定義本字段時必須傳入參數max_digits和decimal_places,用於定義總位數和小數位數。

 

 

ImageField

相似於 FileField,同時驗證上傳的對象是不是一個合法圖片,可選參數有2個:height_field和width_field,有這兩個參數,圖片按照規定的長和高進行存儲。

IntegerField

保存一個整數

IPAddressField

一個字符串形式的IP地址

NullBooleanField

相似於BooleanField,可是多出了一個None選項

PhoneNumberField

帶有美國風格的電話號碼校驗的CharField(格式爲XXX-XXX-XXXX)

PositiveIntegerField

只能輸入非負數的IntegerField

SlugField

只包含字母,數字,下劃線和連字符的輸入,一般同於URL

SmallIntegerField

相似於IntegerField,可是隻有較小的輸入範圍,依賴所使用的數據庫。

TimeField

時間字段,相似於DateTimeField,但只能表達和輸入時間。

URLField

用於保存URL

USStateField

美國州名的縮寫字段

XMLField

XML字符字段,是具備XML合法性驗證的TextField

 

 

 

4.1.4 經常使用字段類型的參數

每一個字段類型都有一些特定的HTML標籤和表單驗證參數,好比heigth_field,path等,但同時每一個字段都有能夠設置的公告方法,好比primary_key參數設置的主鍵字段。

from django.db import models

class Comment(models.Model):
    # 設置主鍵id
    id = models.AutoField(primary_key=True)
  • null:定義是否容許相對應的數據字段爲null,默認設置爲false。除了上述說到的主鍵外,還有其餘參數,以下:
  • blank:定義字段是否能夠爲空。null是一個數據庫中的非空約束;blank用於字段的HTML表單驗證,即判斷用戶是否能夠爲空。
  • choices:定義字段的可選值。該字段的值是一個包含二維元素的元祖。元祖中的第一個值是實際存儲的值,第2個值是HTML頁面中進行選擇時顯示的值。示例代碼以下:
from django.db import models

class Comment(models.Model):
    # 設置主鍵id
    id = models.AutoField(primary_key=True)
    # 定義選擇元祖
    levels = (('1','Very Good'),('2','Good'),('3','Normal'),('4','Bad'))
    level = models.CharField(max_length=10,choices=levels)

上述代碼中定義了level字段用於讓用戶選擇滿意度,其中的1,
2,3,4是在數據庫中實際存儲的數據,而very good、Good、Normal、Bad等是在HTML頁面中供選擇的選項。
  • default:設定默認值,例如:default=」Good」。 
  • help_text:HTML頁面中輸入控件的幫助字符串。
  • unique:定義字段是否爲數據庫的惟一約束。

除了這些名稱的字段外,Django中的全部字段還有一個無名參數,能夠設置該字段在HTML頁面的顯示名稱,好比:

level = models.CharField('客戶滿意度選擇',max_length=10,choices=levels)

4.2 模型類數據操做

4.2.1 數據查詢

定義以下的Django models,用於演示Django的模型基本查詢技術。

from django.db import models

class Comment(models.Model):
    # 設置主鍵id
    id = models.AutoField(primary_key=True)
    # 定義選擇元祖
    levels = (('1','Very Good'),('2','Good'),('3','Normal'),('4','Bad'))
    level = models.CharField('客戶滿意度選擇',max_length=10,choices=levels)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateTimeField()
    n_visits = models.IntegerField()

    def __str__(self):
        return self.headline

(1) Django有2中過濾器用於對記錄進行刷選,以下:Django經過模型的objects對象查詢模型的數據,例以下面的語句查詢Comment模型的全部數據:Comment.objects.all()

  • filter(**kwargs):返回符合條件的數據集。
  • exclude(**kwargs):返回不符合條件的數據集。
  • 例以下面的語句查詢全部pub_date_year的字段是2015的數據: Comment.objects.filter(pub_date_year = 2015)
(2)鏈接查詢
多個filter和exclude能夠連在一塊兒進行查詢,好比查詢全部2015年非1月的n_visits不爲0的記錄:Comment.objects.filter(pub_date_year == 2015).exclude(pub_date_month=1).exclude(n_visits_exact=0)。
咱們能夠看到代碼中的pub_date_year,它並非模型中定義的一個字段,而是Django定義的一種獨特的字段查詢方式,本例中該查詢的含義是「pub_date字段的year屬性爲2015」。基本的表現形式爲  字段名稱_謂詞,既由「雙下劃線鏈接的字段名稱和謂詞」來表達查詢條件。相似的還有不少其餘的謂詞查詢方式,完整的Django謂詞列表以下標所示。
謂詞
含義
示例
等價的sql語句
exact
精確等於
Com.objects.filter(id_exact=14)
Select * from Com where id = 14;
iexact
大小寫不敏感的等於
Com.objects.filter(headline_iexact=」I am ok」)
Select * from Com where upper(headline)=」 I am ok」
contains
模糊匹配
Com.objects.filter(headline_ contains =」good」)
Select * from Com where headline like  」%good%」;
in
包含
Com.objects.filter(id_ in =[1,5,9])
Select * from Com where id in [1,5,9];
gt
大於
 
Com.objects.filter(id_ gt=30)
 
Select * from Com where id > 30;
gte
大於等於
lt
小於
lte
小於等於
startwith
以..開頭
Com.objects.filter(body_text_ startwith=」wl」)
text_ endwith=」wl」
Select * from Com where body_text   like  」good%」 」%good」;
endwith
以..結尾
range
在..範圍內
Com.objects.filter(pub_date_range=(starttime,endtime))
Select * from Com where pub_date between  starttime and endtime;
year
 
Com.objects.filter(pub_date_year == 2015)
Select * from Com where pub_date between  「2015-1-1 00:00:00」 and 「2015-12-31 23:59:59」;
month
day
Week_day
星期幾
isnull
是否爲空
Com.objects.filter(pub_date_isnull = True)
Select * from Com where pub_date  is Null;
 
(3)除了all()、filter()、exclude()等返回數據集的函數,Django還提供了get()函數用於查詢單挑記錄,好比查詢id爲3的記錄:
Com.objects.get(id_exact = 1)
(4)Django還提供了用於查詢指定條數的小標操做,該特性使得Django模型可以支持SQL中的limit和offset。
  • Com.objects.all()[:10]—>返回數據集,查詢前10條記錄。
  • Com.objects.all()[10:20]—>返回數據集,查詢10-20條記錄。
  • Com.objects.all()[1]—>返回數據集,查詢第二條記錄。
(5)Django還提供了order_by操做,示例以下:
    Com.objects.order_by(「headline」):返回數據集,按照headline字段排序。
 
 

4.2.2 數據存儲

    和傳統的sql相比,Django的一個較大的優點是定義了一個統一的方法save(),用於完成模型的insert和update操做。在執行模型的save()函數時,Django會根據模型的主鍵,判斷記錄是否存在,若是存在執行update操做,不存在執行insert操做。

# 新增記錄
obj = Comment(headline='i am ok',body_text='...sdjk',
pub_date = datetime.datetime().now(),n_visits=0)
obj.save()
print(obj.id) # 打印主鍵id22

# 修改記錄數據
obj.body_text = "this is my world, I am god!!"
obj.save()

print(obj.id) # 打印主鍵id=22,和新增後的id相同。

4.2.3 數據刪除 

Django模型提供了delete()方法用於刪除記錄,該方法能夠進行單條和批量刪除。示例代碼以下:

# 刪除id爲3的記錄
Comment.objects.get(id=3).delete()

# 刪除2015年全部的記錄
Comment.objects.filter(pub_date_year = 2015).delete()

4.3 關係操做

利用數據表之間的關係進行數據建模和業務開發是關係型數據庫最主要的功能。Django的模型層對這三種關係模型(1:1,1:N;M:N)都有強大的支持。

4.3.1 一對一關係

在SQL語言中,一對一的關係經過在兩個表之間定義相同的主鍵來完成。在Django的模型層,能夠在任意一個模型中定義OneToOneField字段,而且定義相互之間的一對一關係。以下的代碼在模型Account和Contact之間定義了一對一的關係。

class Account(models.Model):
    user_name = models.CharField(max_length=80)
    password = models.CharField(max_length=255)
    reg_date = models.DateTimeField()

    def __str__(self):
        return "Account:%s" % self.user_name

class Contact(models.Model):
    account = models.OneToOneField(Account,on_delete=models.CASCADE,primary_key=True)
    zip_code = models.CharField(max_length=10)
    address = models.CharField(max_length=80)
    mobile = models.CharField(max_length=20)

    def __str__(self):
        return "%s,%s" % (self.account.user_name,self.mobile)
  • 兩個模型的關係經過Contact模型中的account字段進行定義。上述代碼的解析以下:
  • OneToOneField()函數中的第一個字段參數是被關聯的模型名稱。
  • l  on_delete參數定義當被關聯模型(Account)的記錄被刪除是被模型的記錄如何處理,models.CASCADE定義一樣被刪除。
  • l  模型中的__str__函數用來定義函數模型的顯示字符串,py3只能用str。

 在上述一對一的關係模型中的開發代碼以下所示。

a1 = Account(user_name='wltest')
a1.save()  # 保存一個Account記錄
print(a1)   # 打印a1:<Account:wltest>

a2 = Account(user_name='zxlText')
a2.save()   # 保存一個Account記錄

# 利用a1初始化Contact的account字段,並保存
a3 = Contact(account=a1,mobile='1223123123')
a3.save()
print(a3)   # <Contact:wltest,1223123123>

print(a1.contact)
# <Contact:wltest,1223123123>,經過關係打印,於打印a3的結果相同

print(a3.account)
# <account:wltest>,經過關係打印,於打印a1的結果相同

# a2沒有和Contact創建過關係,因此沒有contact字段。

a1.delete()
# on_delete = models.CASCADE,因此刪除a1時也刪除了a3

4.3.2 一對多關係

在SQL語言中,1:N關係經過在「附表」中設置「主表」的外鍵引用來完成。在Django模型層,可使用models.ForeignKey()來定義外鍵,代碼以下:

from django.db import models

class Account(models.Model):
    user_name = models.CharField(max_length=80)
    password = models.CharField(max_length=255)
    reg_date = models.DateTimeField()
  
    def __str__(self):
        return "Account:%s" % self.user_name

class Contact(models.Model):
    # account = models.OneToOneField(Account,on_delete=models.CASCADE,primary_key=True)
    account = models.ForeignKey(Account, on_delete=models.CASCADE)
    zip_code = models.CharField(max_length=10)
    address = models.CharField(max_length=80)
    mobile = models.CharField(max_length=20)
  
    def __str__(self):
        return "%s,%s" % (self.account.user_name,self.mobile)

上述代碼於一對一關係惟一不一樣的地方在於models.ForeignKey定義了Contact模型中的account字段。這樣一來,每一個Account對象就能夠與多個Contact對象關聯了。模型的使用代碼以下:

def welcome(request):
    a1 = Account(user_name='wl2',password='12343')
    a1.save()  # 保存一條Account記錄 

    # 爲a1創建兩個Contact關聯的對象
    c1 = Contact(account=a1,address='c1',mobile='12312321412')

    c1.save()  # 保存C1記錄
    c2 = Contact(account=a1, address='c2', mobile='12312321412')
    c2.save()  # 保存C2記錄
    data = {c1.address:str(c1.account), c2.address:str(c2.account),'a1':str([a1.contact_set,a1.contact_set.count()])}

    a1.delete()
    return JsonResponse({'status':200,'data':data})

在一對多關係中,每一個主模型對象能夠關聯多個子對象,因此本例中從主模型Account對象尋找附屬模型Contact的屬性時contact_set,經過一個集合返回關聯結果。

說明:XXX_set是Django設定的經過主模型對象訪問附屬模型的對象集合的屬性名。

4.3.3 多對多關係

在SQL語言中,M:N關係經過創建一箇中間關係表來實現,該中間表中定義了到2個主表的外鍵。因此在Django模型層中,開發者也能夠選擇用這兩個1:N關係來定義M:N的關係。這種方式是經過models.ForeignKey來實現。

另一種方式是在django的模型層中定義一個models.ManyToManyField字段來實現的,多對多關係的模型定義代碼以下:

from django.db import models

class Account(models.Model):
    user_name = models.CharField(max_length=80)
    password = models.CharField(max_length=255)
    # reg_date = models.DateTimeField()
  
    def __str__(self):
        return "Account:%s" % self.user_name
  

class Contact(models.Model):
    account = models.ManyToManyField(Account)
    zip_code = models.CharField(max_length=10)
    address = models.CharField(max_length=80)
    mobile = models.CharField(max_length=20)
  
    def __str__(self):
        return "%s,%s" % (self.account.user_name,self.mobile)

上述代碼經過在Contact中定義引用Account的ManyToManyField,實現了2個模型的多對多關聯,對此模型的定義操做演示以下:

# 分別創建並保存Account和Contact的對象
a1 = Account(user_name='ww')
a1.save()
c1 = Contact(mobile='weeee3')
c1.save()
  
# t經過Contact對象創建關係
c1.account.add(a1)

a2 = Account(user_name='jjj')
a2.save()
a2.contact_set.add(c1) # 經過Account對象創建關係
  
a3 = Account(user_name='jjj')
# 對象未保存出錯
a3.contact_set.add(c1) # 經過Account對象創建關係

a1.contact_set.remove()   # 取消單個對象的關聯
a1.contact_set.clear()   # 取消全部對象的關聯

4.4 面向對象ORM

Django模型層ORM的一個強大之處是對模型繼承的支持,該技術將python面向對象的編程方法與數據庫面向關係表的數據有機的結合。支持三種風格的模型集成。相面來介紹這三種繼承方法。

4.4.1 抽象繼承  

抽象類繼承是指父類繼承models.Model,但不會在底層的數據庫中生成相應的數據表,父類的相關屬性字段存儲在子類的數據表中。

它的做用是在多個表有想幹的字段時,可使得開發者將這些字段統必定義在抽象基類中,免於重複定義這些字段。抽象基類的定義經過在模型的Meta中定義屬性abstract=True來實現,示例代碼以下:

class MessageBase(models.Model):
    id  = models.AutoField()
    content = models.CharField(max_length=100)
    user = models.CharField(max_length=20)
    pub_date = models.DateTimeField()
    
    class Meta:
        # 定義本類爲抽象基類
        abstract = True

class Mon(MessageBase):
    headline = models.CharField(max_length=50)
  
class Com(MessageBase):
    life = models.CharField(max_length=30,default='wl',choices=(('1','2'),('sjdk','idi')))

在子類模型的編程中,能夠直接使用父類定義的字段,例如:上述代碼中定義了一個抽象基類MessageBase,用於保存消息的4個字段。子類Mom和Com繼承自MessageBase,並分別定義了本身的一個字段。這3個類映射到數據後,會別定義成2個數據庫表。每一個表都有5個字段

m1 = Mon(user='ds',headline='sds')
m1.content = 'sddhjk'
m1.save()

4.4.2 多表繼承

多表繼承的模型類都在底層的數據庫中生成了相應的數據表管理數據。不管是父表仍是子表都會用數據庫中相對應的數據表維護模型的數據,父類中的字段不會重複的在多個子表中進行定義。從這方面來說,多表繼承纔是真正面向對象的ORM技術。

多表繼承不須要特殊的關鍵字。在Django內部經過在父類和子類之間創建一對一關係來實現多表繼承,示例代碼以下。

from django.db import models

class MessageBase(models.Model):
    id  = models.AutoField()
    content = models.CharField(max_length=100)
    user = models.CharField(max_length=20)
    pub_date = models.DateTimeField()
  
class Mon(MessageBase):
    headline = models.CharField(max_length=50)
  
class Com(MessageBase):
    life = models.CharField(max_length=30,default='wl',choices=(('1','2'),('sjdk','idi')))

仍然能夠直接引用父類定義的字段,同時子類能夠經過父類對象引用訪問父類的示例。上述代碼在數據庫中會實際生成3個數據表。同時在對模型的編程過程當中,子類

# 新建Mon對象,直接在子類中引用父類字段
m1 = Mon(user='ds',headline='sds')
m1.content = 'sddhjk'

m1.save()
# 經過父類引用父類字段
print(m1.messagebase.content)

4.4.3 代理繼承 

    代理模型繼承指父類用於在底層數據庫中管理數據表,而子類不定義數據列。只定義查詢數據集的排序方式等元數據。前兩種繼承模型中都有實際存儲數據的做用,而代理模式繼承中子類只用於管理父類的數據,而不實際存儲數據。設置的方法是在Meta中定義proxy=True屬性來實現,示例代碼以下:

class MessageBase(models.Model):
    id  = models.AutoField()
    content = models.CharField(max_length=100)
    user = models.CharField(max_length=20)
    pub_date = models.DateTimeField()

class Mon(MessageBase):
    class Meta:
        proxy = True
        ordering = ["-pub_date"]

 

 

五.Django視圖層

Django視圖層的主要做用是銜接HTML模板、python程序、HTTP請求等。

5.1 URL映射

URL分發映射配置能夠被看作Django項目的入口配置,經過URL分發能夠指定用戶的每個訪問的後臺python處理函數是什麼。

5.1.1 普通URL映射

每個django項目都有一個urls.py文件用於維護自身的URL dispatcher,該文件的基本內容以下:

from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^welcome',views.welcome),
    url(r'^moments_input/',views.moments_input),
]

程序經過維護urlpatterns列表中的元素完成URL的映射,每一個元素都是一個django.conf.urls.url的實例,函數url()的第1個參數是HTTP路徑,第2個參數是該路徑映射到的python函數名。

5.1.2 正則表達式

正則表達式速查表

符號

說明

例子

 

\

 

將下一個字符標記爲特殊字符

「\n」匹配一個換行符

「\\」匹配一個「\」

「\(」匹配一個「(」

^

字符串的開始位置

「^abc」:以abc開頭

$

字符串的結束位置

「abc$」:以abc結尾

*

前面的子表達式0或者屢次

「2*」匹配「」「2」「2222」等

+

前面的子表達式1或者屢次

「2+」匹配「1」「2」「222」等

?

前面的子表達式0或者1次

「3?」匹配「」或者「3」

.

除\n之外的任意單個字符

 

{n}

匹配n次

「o{2}」:匹配food中的兩個o

{n,}

至少匹配n次

 

{n,m}

匹配n到m次

 

x|y

匹配x或者y

Asd|sdf:匹配Asd或者sdf

[xyz]

匹配xyz中任一字符

[123]匹配1,2或者3

[a-z]

匹配a-z範圍內的字符

 

[^a-z]

匹配不在a-z範圍內的字符

 

5.1.3 命名URL映射

在普通的URL映射中,Django將URL中的變量參數按照路徑中的出現順序傳遞給被調用函數。而命名URL參數映射使得開發者能夠定義這些被傳遞參數的名稱,命名URL參數的定義方式爲 ?p<param_name>pattern,示例代碼以下:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^year/2015/$',views.year2015),
    url(r'^year/?p<year>([0-9]{4})/$',views.year),
    url(r'^year/?p<year>([0-9]{4})/?p<month>([0-9]{2})/$',views.month),
]

上述代碼中的後兩個url()使用命名參數進行了定義,他們調用Views.py文件中的相關函數,調用的方式爲year(request,year=xxxx)和month(request,year=xxxx,month=xx)。

當多個URL映射到一個地址是,只選擇第一個映射。

5.1.4 分佈式URL映射

在實際的大型項目開發中,一個項目可能包含多個Django應用,而每個都有本身的URL映射規則。這個時候講全部的URL映射都保存在一個文件中很是不利於對項目進行維護,因此Django提供了include()函數來進行分佈式的URL映射。在項目djangotest/djangotest/urls/py的文件中引用其餘應用的URL映射文件的代碼以下:

from django.contrib import admin
from django.urls import path
from django.conf.urls import include,url

urlpatterns = [
    url('admin/', admin.site.urls),
    url(r'^app/', include('app.urls')),
]

5.1.5 反向URL映射 

除了以上介紹的幾種映射方式,Django還提供了反向的從映射名到URL地址的解析功能。URL反向解析使得開發者能夠用映射名代替不少須要寫絕對URL路徑的地方,提升了代碼的可維護性。

待續。。。很是重要

 

5.2 視圖函數

視圖函數是Django開發者處理HTTP請求的python函數。在一般的狀況下,視圖函數的功能是經過模型層對象處理數據,而後用以下所示的一種方式返回數據。

  • 直接構造HTTP body
  • 用數據渲染HTML模板文件。
  • 若是有邏輯錯誤,則直接返回HTTP錯誤或者其餘狀態。

5.2.1 直接構造html頁面

對於如下簡單的頁面,能夠直接在視圖函數中構造返回給客戶端的字符串,該功能是經過HttpResponse()函數封裝返回。

from django.http import HttpResponse

def index(request):
    HttpResponse('<h2>我是你爸爸!</h2>')

 

5.2.2 用數據渲染HTML模板

因爲模板文件能夠包含豐富的HTML標籤內容,因此使用渲染模板文件的方法返回數據時一種經常使用的技術。該功能經過render()函數來實現。

from django.shortcuts import render

def index(request):
    render(request,'index.html')

render()函數的第一個參數是HTTP Request,第二個參數是模板文件名,第三個參數是想模板文件中返回的數據,是字典的形式。


5.2.3 返回HTTP錯誤

HTTP的錯誤經過HTTP頭中的status來進行表述,經過給httpResponse函數傳遞status參數能夠返回HTTP的錯誤或者狀態。如:

from django.http import HttpResponseRedirect,HttpResponse 

def index(request):
    HttpResponse(status=404)
經過上述的代碼能夠返回HTTP 404錯誤。可是爲了方便開發者的使用,Django對經常使用的status狀態進行了進一步的封裝,具體的實現以下所示:
  • HttpResponseRedirect:返回的狀態是302,做用是URL的重定向,須要將目標的地址做爲參數進行傳遞。
  • HttpResponseNotModified:返回狀態304,指示瀏覽器顯示上次請求的緩存結果頁面。
  • HttpResponsePermanentRedirect:返回狀態301,和HttpResponseRedirect相似,只不過這是一個永久的重定向。
  • HttpResponseBadRequest:返回狀態400,請求內容錯誤。
  • HttpResponseForbidden:返回403,禁止訪問的錯誤。
  • HttpResponseNotFound:返回404,不能訪問的錯誤。
  • HttpResponseNotAllowed:返回405,訪問方法(get,post)錯誤。
  • HttpResponseServerError:返回500,服務器內部錯誤。

5.3 模板語法

模板文件是一種文本文件,主要又目標文件的內容組成,而後輔以模板的特殊語法用於替換動態內容。下面的代碼是一個功能較爲齊全的模板文件。

{% extend "base.html" %}  # 繼承基類模板

{% block title %}title 內容{% endblock %}  

{% block content %}

  <h1>{{ section.title }}</h1>

  

{% for i in ins %}

  <h3>

    {{ i.code | upper }}

  </h3>

{% endfor %}

{% endblock %}

5.3.1 流程控制

Django模板提供基本的流程控制功能,使用{% for %}語句實現循環邏輯控制以及使用{% if %}語句實現邏輯判斷功能,示例代碼以下:

{% for moment in moments %}
  <h3>
    {{ moment.user | upper }}
  </h3>
{% endfor %}
  
{% if moment.id < 10 %}
  <h3>{{ moment.headline }}</h3>
{% elif moment.id < 20 %}
  <h3>{{ moment.headline }}</h3>
{% else %}
  <h3>{{ moment.headline }}</h3>
{% endif %}

 

5.3.2 模板繼承

模板的繼承功能使得網站前端的設計者能夠將多個頁面的的公用部分編寫在一個模板文件中,而後在其餘的模板文件中繼承,共享這部份內容。因此模板文件能夠分爲兩種類型。

  • 父模板文件:保存功用部分的內容,同時制定頁面的總體結構。父模板文件通常包括頁面頭、導航欄、頁腳、ICP聲明等。
  • 子模板文件:用於實現具體的頁面展現,實現自身特有內容。

5.3.3 過濾器

過濾器在模板中是放在變量後面用於對變量顯示的結果進行控制的技術,變量和過濾器之間用管道符號進行鏈接。具體的過濾器以下圖所示。

過濾器

說明

相關文章
相關標籤/搜索