Python下有許多款不一樣的 Web 框架。Django是重量級選手中最有表明性的一位。許多成功的網站和APP都基於Django。html
Django是一個開放源代碼的Web應用框架,由Python寫成。前端
Django遵照BSD版權,初次發佈於2005年7月, 並於2008年9月發佈了第一個正式版本1.0 。python
Django採用了MVC的軟件設計模式,即模型M,視圖V和控制器C。mysql
因此Django的設計目標就是一款大而全,便於企業開發項目的框架,所以企業應用較爲普遍 react
1 可以快速開發,如Auth,Cache模板
2 MVC設計模式
3 實用的管理後臺
4 自帶ORM,Template,Form,Auth核心
5 組件
6 簡潔的URL設計
7 周邊插件豐富 git
重量級,由於東西大而全
同步阻塞web
Django version | python version |
---|---|
1.8 | 2.7 3.2 3.3 3.4 3.5 |
1.9 1.10 | 2.7 3.4 3.5 |
1.11 | 2.7 3.4 3.5 3.6 |
2.0 | 3.4 3.5 3.6 |
2.1 | 3.5 3.6 3.7 |
建議不要隨便嘗試新版本,由於其可能會有問題sql
python3.5.4 Django 版本2.0 數據庫
mkdir test // 建立test目錄 pyenv virtualenv 3.5.4 test //建立test虛擬帳號 cd test/ pyenv local test //設置虛擬環境
結果以下 django
pip install django==2.0
建立名稱爲test.dj的項目
django-admin startproject testdj .
項目結構以下
上述命令就在當前目錄中建立了Django項目的初始化文件,點表示項目的根目錄
重要文件說明
manage.py:本項目管理的命令行工具,應用建立,數據庫遷移,等都須要其完成, testdj/settings.py: 本項目配置文件,數據庫參數等 testdj/urls.py:URL路徑映射配置,默認狀況下,只配置了/admin的路由 testdj/wsgi:定義WSGI接口信息,通常無需改動
設置本地項目路徑
鏈接遠端項目
鏈接遠端
遠端地址
SSH鏈接
若端口不一樣可修改端口
配置密碼
配置項目映射和相關項目環境
結果以下
數據拉取
數據庫必須啓動,其用戶名密碼必須存在
建立test庫
Django鏈接配置
相關參數詳解
'ENGINE' : 鏈接引擎
'NAME':鏈接數據庫用戶名
'PASSWORD':鏈接數據庫密碼
'HOST':數據庫主機IP地址,缺省字符串,表明localhost,若是是'/'開頭表示Unix socket 鏈接
'POST':端口
數據庫引擎ENGINE
內建的引擎有
django.db.backends.postgresql django.db.backends.mysql django.db.backends.sqlite3 django.db.backends.oracle
django 在配置時須要加載mysql的配置,所以其是全局配置,鏈接數據庫的配置,在啓動時必須被加載,其中settings.py是最先被加載的
數據庫驅動配置
驅動地址
https://docs.djangoproject.com/en/2.2/ref/databases/#mysql-notes
Django支持MySQL 5.5+
Django的官方推薦版本是mysql 1.3.7 +
安裝驅動
pip install mysqlclient
結果以下
執行遷移文件,其自己的數據庫配置
python manage.py migrate
結果以下
python manage.py startapp testapp
admin.py 管理站點模型的聲明文件
models.py 模型層Model類定義
views.py 定義URL 響應函數
migrations包。數據庫遷移文件生成目錄
apps.py 應用的信息定義文件
在 settings.py中,增長testapp應用,目的是爲了後臺管理admin使用。或者遷移 migrate 使用
1 建立管理員
設置用戶名爲admin,密碼爲admin123
./manage.py createsuperuser
結果以下
修改配置文件容許全部主機訪問
啓動
python manage.py runserver 0.0.0.0:8000
默認啓動爲8000端口
以下
若是使用react實現前端的頁面功能,其實Django就不必使用模板,它其實就是一個後臺服務器程序,接受請求,響應數據,接口設計就能夠是一個純粹的Reasrful 風格
模板的目的就是爲了可視化,將數據按照必定的佈局格式輸出,而不是爲了數據處理,因此通常不會有複雜的邏輯,模板的引入實現了業務邏輯和顯示格式的分離,這樣,在開發中,就能夠分工工做,頁面開發完成的頁面佈局設計,後臺開發完成數據處理邏輯的實現
python的模板引擎默認使用Django template language (DTL)構建
在settins.py中,設置模板項目的路徑
名詞解釋
DIRS 列表,定義模板文件的搜索路徑順序
BACKEND 指定項目默認引擎
APP_DIRS 是否運行在每一個已安裝的應用中查找模板
BASE_DIR 是項目的根目錄,os.path.join(BASE_DIR,'templates')就是在manage.py這層創建一個目錄templates,這路徑是後面找模板的地方。
項目目錄中添加相關文件夾並在其中建立index.html文件
模板處理2個步驟
1 加載模板
模板是一個文件,須要從磁盤中讀取並加載,要將模板放置在上述指定的目錄中2 渲染
模板須要使用內容數據來渲染,生成對應的HTML文件內容
在testdj/urls.py中配置以下
相關代碼
from django.contrib import admin from django.urls import path from django.conf.urls import url # 導入url用於匹配多個後綴服務 from django.shortcuts import render # 導入渲染模板 def index(request): print (request) print (type(request)) return render(request,'index.html',{'user':'hello world'}) urlpatterns = [ url(r'^admin/', admin.site.urls), # 正則匹配,以admin 開頭的調度到admin.site.urls中 url(r'^index/',index), #同上 url(r'^$',index), ]
render 源碼以下
def render(request, template_name, context=None, content_type=None, status=None, using=None): """ Return a HttpResponse whose content is filled with the result of calling django.template.loader.render_to_string() with the passed arguments. """ content = loader.render_to_string(template_name, context, request, using=using) return HttpResponse(content, content_type, status)
上述中還能夠傳遞狀態碼等參數,但第一個必須是request,第二個必須是模板名稱,
處理模塊填充相關問題
def render_to_string(template_name, context=None, request=None, using=None): """ Load a template and render it with a context. Return a string. template_name may be a string or a list of strings. """ if isinstance(template_name, (list, tuple)): template = select_template(template_name, using=using) # 解決模板找到模板名稱的問題,在配置文件中尋找 else: template = get_template(template_name, using=using) return template.render(context, request) # 此處是使用模板來填充數據,並將其輸出出來,其中包含請求和響應內容
搜索模板相關代碼
def get_template(template_name, using=None): """ Load and return a template for the given name. Raise TemplateDoesNotExist if no such template exists. """ chain = [] engines = _engine_list(using) for engine in engines: try: return engine.get_template(template_name) except TemplateDoesNotExist as e: chain.append(e) raise TemplateDoesNotExist(template_name, chain=chain)
index 代碼以下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主頁</title> </head> <body> test <h1>{{ user }}</h1> <!--此處必須和前面的最後一列中的名稱相對應,不然將不能被識別到--> </body> </html>
加載方法至關於使用open將文件打開,渲染方法將其中的{{}}中的內容進行填充,填充好後交給httpresponse 的body,進行傳遞頭部,約定編碼,相關壓縮狀況,當正文來了後先看編碼格式,後看title,最後加載body的渲染內容
下載是不渲染的,發起HTTP請求,服務器將文件打開,文件流傳輸,其類型是普通文件,其不會渲染成dom樹,其不會作相關的操做,下載不須要dom,只有轉換成DOM才能渲染,
from django.contrib import admin from django.urls import path from django.http import HttpResponse,JsonResponse from django.conf.urls import url # 導入url用於匹配多個後綴服務 from django.shortcuts import render # 導入渲染模板 def index(request): print (request) print (type(request)) return JsonResponse({'user':'hello world'}) # 此處返回結果爲一個json格式的數據 urlpatterns = [ url(r'^admin/', admin.site.urls), # 正則匹配,以admin 開頭的調度到admin.site.urls中 url(r'^index/',index), #同上 url(r'^$',index), ]
構建結果以下
https://docs.djangoproject.com/en/2.2/ref/templates/builtins/
語法 {{variable}}
變量名由字母,數字,下劃線,點號組成
點號使用時,須要遵循的順序:
1 字典查找,如foo['bar'],把foo當作字典,bar當作key
2 屬性或方法的查找,如foo.bar 是把foo當作對象,bar當作屬性或者方法
3 數字索引查找,如foo[bar],把foo當作列表同樣,將使用索引訪問
若是變量未能找到,則缺省插入空字符串
在模板中調用方法,不能加小括號,天然也不能傳遞參數
{{ my_dict.keys }} 這樣是對的,不能寫成 {{ my_dict.keys() }}
基本語法以下
{% if condition %}
... display
{%end%}或者
{% if condition1 %}
..display 1
{% elif condition2 %}
...display 2
{% else %}
...display 3
{% endif %}條件也支持and,or,not
注意:由於這些標籤是斷開的,因此不能像python同樣使用鎖緊就能夠表示出來,必須有一個結束表親,如 endif endfor
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主頁</title> </head> <body> <ul> {% for x in name %} <li> {{ x }} </li> {% endfor %} </ul> </body> </html>
下面是便利字典的值
return render(request,'index.html',{'name':dict(zip('abcd',range(4)))})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主頁</title> </head> <body> <ul> {% for x in name.values %} <li> {{ x }} </li> {% endfor %} </ul> </body> </html>
結果以下
變量 | 說明 |
---|---|
forloop.counter | 當前循環從1開始計數 |
forloop.counter 0 | 當前循環從0開始計數 |
forloop.revcounter | 從循環的末尾開始倒計數到1 |
forloop.revcounter0 | 從循環的末尾開始倒計數到0 |
forloop.first | 第一次進入循環 |
forloop.last | 最後一次進入循環 |
forloop.parentloop | 循環嵌套時,內存當前玄幻的外層循環 |
return render(request,'index.html',{'name': [1,2,3,4,5,6]})
翻轉,此處僅限於列表
<ul> {% for x in name reversed %} <li> {{ x }} </li> {% empty %} <li> default </li> {%endfor%} </ul>
empty ,爲空或者不存在時執行此命令
以下
<ul> {% for x in mysql reversed %} <li> {{ x }} </li> {% empty %} <li> default </li> {%endfor%} </ul>
此處的mysql是不存在的,所以下面的結果是
後端代碼以下
return render(request,'index.html',{'name': dict(zip('abcd',range(4)))})
<ul> {% for k,v in name.items %} <li> {{ forloop.first }} </li> <li> {{ forloop.last }} </li> {%endfor%} </ul> <h1> 分割線 </h1> <ul> {% for k,v in name.items %} <li> {{ forloop.counter}} {{ k }} {{ v }} </li> {%endfor%} </ul> <h1> 分界線 </h1> <ul> {% for k,v in name.items %} <li> {{ forloop.counter0 }} {{ k }} {{ v }} </li> {%endfor%} </ul>
結果以下
{% ifequal %} 標籤比較兩個值,當其相等時,顯示在其標籤之間的全部值,
{%ifequal user currentuser %}
<h1> welcome! </h1>
{% endifequal %}和{% if %}相似,{% ifequal %} 支持可選的 {% else %}標籤。
後端代碼以下
return render(request,'index.html',{'name': 'mysql'})
顯示層代碼以下
{% ifequal name 'mysql' %} <h1> Site </h1> {%else%} <h1>Not Site </h1> {%endifequal%} </body> </html>
csrf_token 用於跨站請求僞造保護,防止跨站***的
{% csrf_token%}
單行註釋
{#這是一個註釋#}
多行註釋
{% comment %}
這是多行註釋
{%endcomment%}
模板過濾器能夠在變量被顯示以前修改它
語法 {{ 變量 | 過濾器 }}
過濾器使用管道符 | , 例如 {{name| lower}} , {{name}} 變量被過濾器 lower 處理後,文檔大寫轉換文本爲小寫。
過濾管道能夠被套接,一個過濾器管道的輸出又能夠做爲下一個管道的輸入,例如{{my_list | first | upper }},將列表第一個元素並將其轉換爲大寫。
過濾器傳遞參數
有些過濾器能夠被傳遞參數,過濾器的參數跟隨冒號以後而且老是以雙引號包含如 {{bio| trunactewords:"30"}},截取顯示變量的bio的前30個詞。
{{my_list | join:"."}}將my_list的全部元素使用逗號鏈接起來
過濾器 | 說明 | 舉例 | ||
---|---|---|---|---|
first | 取列表第一個元素 | |||
last | 去列表最後一個元素 | |||
yesno | 變量能夠是 True,False,None,yesno的參數給定的逗號分隔的三個值,返回3個值中的一個。True對應飛一個,False對應第二個,None對應第三個,若是參數只有2個,則None等效於False處理 | {{value | yesno:"yeah,no,maybe"}} | |
add | 加法,參數是負數就是減法 | 數字加{{value | add:"100"}} 列表合併{{mylist | add:newlist}} |
divisibleby | 可否被整除 | {{vaule | divisibleby:"3"}}可以被3整除返回True | |
addslashes | 在反斜槓,單引號或者雙引號前面加上反斜槓 | {{value | addslashes}} | |
length | 返回變量的長度 | {% if my_list | length >1 %} | |
default | 變量等價False則使用缺省值 | {{value | default:"nothing"}} | |
default_if_none | 變量爲None使用缺省值 | {{value | default_if_none:"noting"}} |
練習
計數返回一種類型的值,偶數返回一種類型的顏色
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主頁</title> </head> <body> <u1> {% for v in name.values %} {% if forloop.counter0|divisibleby:"2" %} <li style="color:red"> {{ v }} </li> {% else %} <li style="color:seagreen"> {{ v }} </li> {% endif %} {% endfor %} </u1> </body> </html>
第二種
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主頁</title> </head> <body> <u1> {% for v in name.values %} <li style='color: {{ forloop.counter0 | divisibleby:"2"| yesno:"red,blue"}}'>{{v}}</li> {% endfor %} </u1> </body> </html>
結果以下
Django 會爲模型提供一個object對象,其是Django.db.models.manager.Manager類型,用於與數據庫交互,當定義模型類的時候沒有指定管理器,則Django會爲模型類提供一個object管理器。
若是在模型中手動指定管理器後,Django不在提供默認的object管理器了
管理器是Django的模型進行數據庫查詢操做的接口,Django應用的每個模型都至少擁有一個管理器。
查詢會返回結果的集,是Django.db.models.query.QuerySet類型
其是惰性求值,和sqlalchemy同樣,結果就是查詢的集。
其是可迭代對象。
1 惰性求值:
建立查詢集不會帶來任何數據庫的訪問,直到調用數據時,纔會訪問數據庫,在迭代,序列化,if語句中都會當即求值。2 緩存
每個查詢都包含一個緩存,來最小化對數據庫的訪問
新建查詢集,緩存爲空,首次對查詢集請求值時,會發生數據查庫查詢,Django會把查詢的結果緩存在這個緩存中,並返回請求的結果,接下來對查詢集的求值將使用緩存的結果。
觀察下面2個例子是要看真正生成的語句了
1 沒有使用緩存,每次都要查詢數據庫,查詢了兩次
[user.name for user in User.objects.all()]
[user.name for user in User.objects.all()]2 下面的語句使用緩存,由於其使用同一個結果集
qs = User.objects.all()[user.name for user in qs ]
[user.name for user in qs ]
查詢集對象能夠直接使用索引下表的方式(不支持負向索引),至關於SQL語句中的limit 和 offset 字句,注意使用索引返回的新結果集,依然是惰性求值,不會當即查詢。
qs = User.objects.all()[20:40]
SQL 等價:Limit 20 offset 20
qs = User.obeject.all()[20:30]
SQL 等價:Limit 10 offset 20
column | column |
---|---|
all() | Text |
filter() | 過濾,返回知足條件查詢的數據 |
exclude() | 排除,排除知足條件的數據 |
order_by() | |
values() | 返回一個對象的字典的列表,像JSON |
下屬等價
filter(k1=v1).filter(k2=v2)等價於 filter(k1=v1,k2=v2)
filter(pk=10)這裏pk指的是主鍵,不用關心主鍵的名字字段,固然也可使用主鍵來進行相關的過濾操做
返回單值的狀況
column | column |
---|---|
get() | 僅返回單個知足條件的對象,若是未能返回對象則排除DoesNotExists異常,若是能返回多條,拋出MultipleObjectReturned 異常 |
count() | 返回當前查詢的總條數 |
first() | 返回第一個對象 |
last() | 返回最後一個對象 |
exist() | 判斷查詢集中是否有數據,若是有則返回True |
字段查詢(field Lookup) 表達式
字段查詢表達式能夠做爲filter(),exclude(),get() 的參數,實現的是where字句的功能語法: 屬性(字段) 名稱_比較運算符=值
注意: 屬性名和運算符之間使用雙下劃線
column | column | |
---|---|---|
exact | filter(isdeleted=False) filter(isdeleted__exact=False) | 嚴格等於,能夠省略不寫 |
contains | exclude(title__contains='天') | 是否包含,大小寫敏感,等價於 like '%天%' |
startswith endswith | filter(title__startswith='天') | 以什麼開頭,以什麼結尾,大小寫敏感 |
isnull isnotull | filter(title__isnull=False) | 是否爲null |
iexact,iconains,istartswitch,iendswith | i 的意思是忽略大小寫 | |
in | filter(pk__in=[1,2,3,4]) | 是否在指定返回的數據中 |
gt,gte,lt,lte | filter(id__gt=3) filter(pk__ltd=3),filter(pub_date__gt=date(2000,1,1)) | 大於,小於等 |
year,month,day,week_day,hour,minute,second | filter(pub_date__year=2000) 對日期類型屬性處理 |
雖然Django 提供傳入條件的方式,可是不方便,它還提供了Q對象來解決。
Q對象是Django.db.modules.Q,可使用 &(and) , |(or)操做符來組成邏輯表達式,~ 表示not
from django.db.models import Q User.objects.filter(Q(pk__lt=6)) # 不如直接寫 User.objects.filter(pk<6) User.objects.filter(pk__gt=6).filter(pk_lt=10) #與 User.objects.filter(Q(pk__gt=6) & (pk__lt=10)) # 與 User.objects.filter(Q(pk=6) | Q(pk=10)) # 或 User.objects.filter(~Q(pk__lt<6)) # 非
可以使用&| 和Q對象來構造複雜的邏輯表達式
過濾器函數可使用一個或多個Q對象
若是混用關鍵字參數和Q對象,那麼Q對象必須位於關鍵字參數的前面,全部參數都將and在一塊兒
字段類 | 說明 |
---|---|
AutoField | 自增的整數字段,若是不指定Django會爲模型類型自動增長主鍵字段 |
BooleanField | 布爾值字段,True和False,對應表單控件CheckboxInput |
NullBooleanField | 比BooleanField 多一個空值 |
CharField | 字符串,max_length 設定字符串長度,表單控件TextInput |
TextField | 大文本字段,通常超過4000個字符使用,對應表單控件Textarea |
IntegerField | 整數字段 |
BigIntegerField | 更大整數字段,8字節 |
DecimalField | 使用Python的Decimal實例表示十進制的浮點數,max_digits 總位數,decimal_places 小數點後的位數 |
FloatField | python中的Float實例表示的浮點數 |
DateField | 使用python的datetime.date 實例表示的日期,auto_now=False每次修改對象自動設置爲當前時間,auto_now_add=False對象第一次建立時自動設置爲當前時間,auto_now_add,auto_now,default互斥,對應控件爲TextInput,關聯了一個js編寫的日曆控件 |
TimeField | 使用python的datetime.time實例表示時間,參數同上 |
DateTimeField | 使用python的datetime.datetime實例表示的時間,參數同上 |
FileField | 一個上傳文件的字段 |
ImageField | 繼承了FileField 的全部屬性和方法,可是對上傳文件進行校驗,確保是一個有效的圖片 |
值 | 說明 |
---|---|
db_column | 表中字段的名稱,若是未指定,則使用屬性名 |
primary_key | 是否爲主鍵 |
unique | 是不是惟一 |
default | 缺省值,這個缺省值不是數據庫字段的缺省值,而是新對象產生的是夠被填入的缺省值 |
null | 表的字段是否能夠爲null,默認爲False |
db_index | 字段是否有索引 |
類 | 說明 |
---|---|
ForeignKey | 外鍵,表示一對多 ForeignKey('production.Manufacturer')自關聯 ForeiginKey('self') |
ManyToMaryField | 表示多對多 |
OneToOneField | 表示一對一 |
一對多時,自動建立會增長_id後綴。
從一訪問多,使用 對象.小寫模型類_set
從一訪問一,使用 對象.小寫模型類
訪問 id 對象.屬性_id
基類 models.Model
表名不指定默認使用<appname>_<model_name>,使用Meta類修改表名
相關代碼以下
from django.db import models # Create your models here. class User(models.Model): class Meta: db_table='user' # 定義數據庫表名 id = models.AutoField(primary_key=True) # 定義主鍵自增字段 name=models.CharField(max_length=48,null=False) # 定義name爲浮點型,且其不能爲空 email=models.CharField(max_length=64,unique=True,null=False) # 定義郵件爲浮點類型,且其必須惟一,不能爲空 password=models.CharField(max_length=128,null=False) # 定義密碼類型,其爲浮點數,且不能爲空 def __repr__(self): return '<user {} {}>'.format(self.id,self.name) __str__=__repr__
遷移 migration
遷移:從模型定義生成數據庫的表
1 在項目根目錄執行下面文件生成遷移文件
python manage.py makemigrations
結果以下
修改過Model類,還須要調用makemigrations,而後migrate,遷移文件的序號會增長
注意:遷移的應用必須在settings.py 的 INSTALLED_APPS 中註冊
2 在項目的根目錄執行遷移生成數據庫的表
python manage.py migrate
結果以下