使用框架簡單快速開發特定的系統。
pip freeze > requirements.txt
pip install -r requirements.txt
一 MVC和MTV模式
二 簡介
Django時有Python開發的一個免費的開源網站框架,可以用于快速搭建高性能、優雅的網站。
Django框架的特點:
- 強大的數據庫功能
- 自帶強大的后臺功能
- 通過正則匹配隨意定義的網址
- 強大易擴展的模板系統
- 緩存系統
- 國際化
三 Django安裝方式
1.利用pip安裝Django。
oliver@oliver-G460:~$ sudo pip3 install Django
2.利用源碼包安裝Django。
oliver@oliver-G460:~$ tar -zxvf django-1.10.xx.tar.gz
解壓后進入目錄,執行:
python3 setup.py install
3.利用Linux自帶源安裝Django。
sudo apt-get install python3-django
檢查Django是否安裝成功:
oliver@oliver-G460:~$ python3
Python 3.5.2 (default, Sep 10 2016, 08:21:44)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.VERSION
(1, 10, 2, 'final', 0)
如果希望安裝不同版本的Django環境,則需要通過virtualenv來管理多個開發環境。
四 Django項目創建
方式一:用命令創建項目和app
1. 創建一個新的Django項目
2. 創建app
python3 manage.py startapp app-name 或 django-admin.py startapp app-name
需要注意的是,通過命令行創建的項目,在settings.py中,如app名稱和模板路徑及templates目錄等信息要自己添加。
方式二:用Pycharm創建
在File→New Project中選擇Django,輸入項目名稱mysite和應用名稱myApp,完成創建。
創建完成后, 用Pycharm打開項目,查看項目和app目錄文件
- manage.py:用于管理Django站點。
- settings.py:項目所有的配置信息,包含項目默認設置,數據庫信息,調試標識以及其它工作變量等。
- urls.py:負責把URL映射到視圖函數,即路由系統。
- wsgi.py:內置runserver命令的WSGI應用配置。
五 Django urls(路由系統)
即urls.py文件。其本質是建立url與其所調用的視圖函數的映射關系,以此來規定訪問什么網址去對應什么內容,執行哪個視圖函數。
urlpatterns = [
url(正則表達式,views視圖函數,[參數],[別名]),
]
說明(括號中四部分的意義):
- 正則表達式字符串來匹配瀏覽器發送到服務端的URL網址
- 可調用的視圖函數對象。先引入(import)再使用
- 要傳給視圖函數的默認參數(字典形式)
- name,即別名。HTML中form表單參數action屬性值使用此別名后,即便url發生變化,也無需在HTML中批量進行修改。
1 URL配置舉例:


from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), #url(r'^articles/[0-9]{4}/$', views.year_archive), url(r'^articles/([0-9]{4})/$', views.year_archive), #no_named group url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
用()括起來表示保存為一個子組,每個子組作為一個參數(無名參數),被views.py中的對應函數接收。參數個數與視圖函數中的形參個數要保持一致。
(注意:當匹配到第一個url后立即返回,不再向下查找匹配。)
2 帶命名的組Named group(?P<>)用法
?P<group_name> 表示帶命名的參數,例如:將year='2016'作為一個整體傳個視圖函數。此處的組名稱必須與視圖函數中的形參名稱一致。由于有參數名稱與之對應,所以視圖函數有多個形參時,不需要考慮參數的先后順序。
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), # year=2016 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), ]
3 默認參數(可選)
如下所示,如果請求地址為/blog/2016,表示將year='2016',foo='bar'傳給視圖函數,視圖函數中必須有相同名稱的形參來接收值。
from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]
4 name別名(可選)
固定用法:
url(r'^/index/',views.index,name='bieming')
如果url中的路徑修改為/index2/,對應的模板,甚至還視圖中的跳轉,以及 models.py 中也可能有獲取網址的地方。每個地方都要改,修改的代價很大,一不小心,有的地方沒改過來,那個就不能用了。
因此,在需要跳轉或獲取網址的地方,使用別名設置的名稱,以后便可以隨意修改url了。


urlpatterns = [ url(r'^index',views.index,name='bieming'), url(r'^admin/', admin.site.urls), # url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ] ################### def index(req): if req.method=='POST': username=req.POST.get('username') password=req.POST.get('password') if username=='alex' and password=='123': return HttpResponse("登陸成功") return render(req,'index.html') ##################### <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {# <form action="/index/" method="post">#} <form action="{% url 'bieming' %}" method="post"> 用戶名:<input type="text" name="username"> 密碼:<input type="password" name="password"> <input type="submit" value="submit"> </form> </body> </html> #######################
5 URLconf
一個網站包含成千上萬個URL,如果所有的URL映射都放在一個文件下,很可能會出錯,也不便與維護。
因此,我們在每個app應用下分別創建一個urls目錄,將不同的請求分發給不同app下的urls去匹配,如:對于/blog/index/請求直接交給‘blog.urls’去處理,清晰明確,更方便管理。
六 Django views(視圖函數)
http請求中產生的兩大核心對象:
http請求:HttpRequest對象
http響應:HttpResponse對象
所在位置:django.http
request就是指HttpRequest。
1 HttpRequest對象的屬性和方法
屬性 | 描述 |
---|---|
path | 請求頁面的全路徑,不包括域名—例如, "/music/bands/the_beatles/"。 |
method | 請求中使用的HTTP方法的字符串表示。全大寫表示。 |
GET | 包含所有HTTP GET參數的類字典對象 |
POST | 包含所有HTTP POST參數的類字典對象 |
REQUEST | 為了方便,該屬性是POST和GET屬性的集合體,但是有特殊性,先查找POST屬性,然后再查找GET屬性 |
COOKIES | 包含所有cookies的標準Python字典對象。Keys和values都是字符串。 |
FILES | 包含所有上傳文件的類字典對象。FILES中的每個Key都是<input type="file" name="" /> 標簽中name屬性的值. FILES中的每個value 同時也是一個標準Python字典對象,包含下面三個Keys:(Filename: 上傳文件名,用Python字符串表示;content-type: 上傳文件的Content type;content: 上傳文件的原始內容)注意:只有在請求方法是POST,并且請求頁面中<form> 有enctype="multipart/form-data" 屬性時FILES才擁有數據。否則,FILES 是一個空字典。 |
META | 包含所有可用HTTP頭部信息的字典,例如:(CONTENT_LENGTH,CONTENT_TYPE,QUERY_STRING: 未解析的原始查詢字符,串,REMOTE_ADDR: 客戶端IP地址REMOTE_HOST: 客戶端主機名,SERVER_NAME: 服務器主機名,SERVER_PORT: 服務器端口);META 中這些頭加上前綴HTTP_最為Key, 例如:(HTTP_ACCEPT_ENCODING,HTTP_ACCEPT_LANGUAGE,HTTP_HOST: 客戶發送的HTTP主機頭信息,HTTP_REFERER: referring頁,HTTP_USER_AGENT: 客戶端的user-agent字符串,HTTP_X_BENDER: X-Bender頭信息) |
user | 是一個django.contrib.auth.models.User 對象,代表當前登錄的用戶。如果訪問用戶當前沒有登錄,user將被初始化為django.contrib.auth.models.AnonymousUser的實例。見例子1 |
session | 唯一可讀寫的屬性,代表當前會話的字典對象。只有**Django中的session支持時該屬性才可用。 |
raw_post_data | 原始HTTP POST數據,未解析過。 高級處理時會有用處。 |
method | 描述 |
---|---|
__getitem__(key) | 返回GET/POST的鍵值,先取POST,后取GET。如果鍵不存在拋出 KeyError。這是我們可以使用字典語法訪問HttpRequest對象。例如:request["foo"]等同于先request.POST["foo"] 然后 request.GET["foo"]的操作。 |
has_key() | 檢查request.GET or request.POST中是否包含參數指定的Key。 |
get_full_path() | 返回包含查詢字符串的請求路徑。例如, "/music/bands/the_beatles/?print=true" |
is_secure() | 如果請求是安全的,返回True,就是說,發出的是HTTPS請求。 |
get_full_path(), 比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的結果就是/index33/?name=123
req.path得到的結果是:/index33
2 HttpResponse對象的屬性和方法
對于HttpRequest對象來說,是由django自動創建的,但是,HttpResponse對象就必須我們自己創建。每個view請求處理方法必須返回一個HttpResponse對象。
HttpResponse類在django.http.HttpResponse
在HttpResponse對象上擴展的常用方法:
頁面渲染: render()(推薦) 或 render_to_response(), 頁面跳轉: redirect("路徑") locals(): 可以直接將函數中所有的變量傳給模板
七 Django templates(模板)
模板由HTML+邏輯控制代碼組成。
1 變量
使用雙大括號來引用變量
語法格式: {{var_name}}
2 Template和Context對象
渲染操作流程:
一旦創建Template對象之后,可以用context傳遞數據給它,它是一系列變量和它們值的集合,模板使用它來賦值模板變量標簽和執行塊標簽
context在django里表現為Context類,在django.template模塊中
Context類構造是一個可選參數:一個字典映射變量和它們的值
創建一系列Context對象之后,調用Template對象的render()方法并傳遞Context對象來填充模板
同一個模板渲染多個context:
1 >>>from django,template import Template,Context 2 >>>t=Template("My name is {{name}},I love{{language}}") 3 >>>c=Context({'name':'BeginMan','language':'Python/Js/C#'}) 4 >>>t.render(c) 5 --------------------------------output---------------------------------------------- 6 My name is BeginMan ,I love Python/Js/C#
推薦寫法:
def current_time(req):
now=datetime.datetime.now()
return render(req, 'current_datetime.html', {'current_date':now}) # 字典部分指定就是Context對象,render()方法將Context對象的鍵值傳遞給模板,并填充模板。
3 深度變量查找
context不僅能傳遞簡單的參數(字符串),也可以傳遞列表和字典對象。


1 #最好是用幾個例子來說明一下。 2 # 首先,句點可用于訪問列表索引,例如: 3 4 >>> from django.template import Template, Context 5 >>> t = Template('Item 2 is {{ items.2 }}.') 6 >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) 7 >>> t.render(c) 8 'Item 2 is carrots.' 9 10 #假設你要向模板傳遞一個 Python 字典。 要通過字典鍵訪問該字典的值,可使用一個句點: 11 >>> from django.template import Template, Context 12 >>> person = {'name': 'Sally', 'age': '43'} 13 >>> t = Template('{{ person.name }} is {{ person.age }} years old.') 14 >>> c = Context({'person': person}) 15 >>> t.render(c) 16 'Sally is 43 years old.' 17 18 #同樣,也可以通過句點來訪問對象的屬性。 比方說, Python 的 datetime.date 對象有 19 #year 、 month 和 day 幾個屬性,你同樣可以在模板中使用句點來訪問這些屬性: 20 21 >>> from django.template import Template, Context 22 >>> import datetime 23 >>> d = datetime.date(1993, 5, 2) 24 >>> d.year 25 >>> d.month 26 >>> d.day 27 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') 28 >>> c = Context({'date': d}) 29 >>> t.render(c) 30 'The month is 5 and the year is 1993.' 31 32 # 這個例子使用了一個自定義的類,演示了通過實例變量加一點(dots)來訪問它的屬性,這個方法適 33 # 用于任意的對象。 34 >>> from django.template import Template, Context 35 >>> class Person(object): 36 ... def __init__(self, first_name, last_name): 37 ... self.first_name, self.last_name = first_name, last_name 38 >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.') 39 >>> c = Context({'person': Person('John', 'Smith')}) 40 >>> t.render(c) 41 'Hello, John Smith.' 42 43 # 點語法也可以用來引用對象的方法。 例如,每個 Python 字符串都有 upper() 和 isdigit() 44 # 方法,你在模板中可以使用同樣的句點語法來調用它們: 45 >>> from django.template import Template, Context 46 >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}') 47 >>> t.render(Context({'var': 'hello'})) 48 'hello -- HELLO -- False' 49 >>> t.render(Context({'var': '123'})) 50 '123 -- 123 -- True' 51 52 # 注意這里調用方法時并* 沒有* 使用圓括號 而且也無法給該方法傳遞參數;你只能調用不需參數的 53 # 方法。
4 變量過濾器filter
語法格式: {{obj|filter:param}}


1 # 1 add : 給變量加上相應的值 2 # 3 # 2 addslashes : 給變量中的引號前加上斜線 4 # 5 # 3 capfirst : 首字母大寫 6 # 7 # 4 cut : 從字符串中移除指定的字符 8 # 9 # 5 date : 格式化日期字符串 10 # 11 # 6 default : 如果值是False,就替換成設置的默認值,否則就是用本來的值 12 # 13 # 7 default_if_none: 如果值是None,就替換成設置的默認值,否則就使用本來的值 14 15 16 #實例: 17 18 #value1="aBcDe" 19 {{ value1|upper }} 20 21 #value2=5 22 {{ value2|add:3 }} 23 24 #value3='he llo wo r ld' 25 {{ value3|cut:' ' }} 26 27 #import datetime 28 #value4=datetime.datetime.now() 29 {{ value4|date:'Y-m-d' }} 30 31 #value5=[] 32 {{ value5|default:'空的' }} 33 34 #value6='<a href="#">跳轉</a>' 35 36 {{ value6 }} 37 38 {% autoescape off %} 39 {{ value6 }} 40 {% endautoescape %} 41 42 {{ value6|safe }} 43 44 {{ value6|striptags }} 45 46 #value7='1234' 47 {{ value7|filesizeformat }} 48 {{ value7|first }} 49 {{ value7|length }} 50 {{ value7|slice:":-1" }} 51 52 #value8='http://www.baidu.com/?a=1&b=3' 53 {{ value8|urlencode }} 54 value9='hello I am yuan'
5 常用標簽(tag)
語法格式: {% tags %}
(1) {% if %}
(2) {% for %}
(3) {% csrf_token %}
(4) {% url %} :引用路由配置的地址
(5) {% with %} :用簡短的變量名代替復雜的變量名
(6) {% verbatim %} :禁止render
(7) {% load %} :加載標簽庫
6 自定義filter和simple_tag
(1)在app下創建templatetags目錄或模塊,目錄名稱必須這樣寫。
(2)創建.py文件,如my_tags。(其中,register名稱不可改變)
(3)在使用自定義filter和simple_tag的html文件之前,通過 {% load my_tags %}導入前面自己創建的my_tags標簽庫。(注意:settings中INSTALLED_APPS中必須添加當前的app名稱,否則找不到自定義的tags)
(4)調用自定義的filter和simple_tag。
filter可以用在if等語句后,simple_tag不可以:
{% if num|filter_multi:30 > 100 %}
{{ num|filter_multi:30 }}
{% endif %}
7 extend模板繼承
將shopping_car.html和ordered.html中大量重復的代碼提取出來,寫入base.html中,不同的部分分別寫在各自模板中,通過extends繼承base.html中的公共部分。


1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 *{ 8 margin: 0; 9 } 10 11 .top{ 12 height: 45px; 13 background-color: darkblue; 14 } 15 16 .menu{ 17 width: 20%; 18 height: 700px; 19 background-color: cornflowerblue; 20 float: left; 21 margin-top: 5px; 22 } 23 24 .menu a{ 25 display: block; 26 text-align: center; 27 } 28 29 .content{ 30 width: 80%; 31 height: 700px; 32 float: left; 33 margin-top: 5px; 34 background-color: lightgray; 35 } 36 </style> 37 </head> 38 <body> 39 <div class="top"></div> 40 <div class="menu"> 41 <a href="/shopping_car/">Shopping Car</a> 42 <a href="/ordered/">Ordered</a> 43 </div> 44 <div class="content"> 45 {% block content %} 46 {% endblock %} 47 </div> 48 </body> 49 </html>
shopping_car.html:
1 {% extends 'base.html' %} 2 3 4 {% block content %} 5 <a>購物車</a> 6 {% endblock %}
ordered.html:
1 {% extends 'base.html' %} 2 3 4 {% block content %} 5 <a>訂單</a> 6 {% endblock %}
八 Django modules(模型)
1 django默認支持sqlite,mysql, oracle,postgresql數據庫。
<1> sqlite
django默認使用sqlite的數據庫,默認自帶sqlite的數據庫驅動
引擎名稱:django.db.backends.sqlite3
<2> mysql
引擎名稱:django.db.backends.mysql
2 mysql驅動程序
MySQLdb(mysql python)
mysqlclient
MySQL
PyMySQL(純python的mysql驅動程序)
3 Django的項目中默認使用sqlite數據庫,在settings中設置如下:
如果想要使用mysql數據庫,只需要做如下更改:
注意:NAME即數據庫的名字,在mysql連接前該數據庫必須已經創建,而上面的sqlite數據庫下的db.sqlite3則是項目自動創建
USER和PASSWORD分別是數據庫的用戶名和密碼。
設置完后,再啟動我們的Django項目前,我們需要**我們的mysql。
然后,啟動項目,會報錯:no module named MySQLdb
這是因為django默認你導入的驅動是MySQLdb,可是MySQLdb對于py3有很大問題,所以我們需要的驅動是PyMySQL
所以,我們只需要找到項目名文件下的__init__,在里面寫入:
ORM(對象關系映射)
對象-關系映射(Object/Relation Mapping,簡稱ORM),是隨著面向對象的軟件開發方法發展而產生的。面向對象的開發方法是當今企業級應用開發環境中的主流開發方法,關系數據庫是企業級應用環境中永久存放數據的主流數據存儲系統。對象和關系數據是業務實體的兩種表現形式,業務實體在內存中表現為對象,在數據庫中表現為關系數據。內存中的對象之間存在關聯和繼承關系,而在數據庫中,關系數據無法直接表達多對多關聯和繼承關系。因此,對象-關系映射(ORM)系統一般以中間件的形式存在,主要實現程序對象到關系數據庫數據的映射。 面向對象是從軟件工程基本原則(如耦合、聚合、封裝)的基礎上發展起來的,而關系數據庫則是從數學理論發展而來的,兩套理論存在顯著的區別。為了解決這個不匹配的現象,對象關系映射技術應運而生。 讓我們從O/R開始。字母O起源于"對象"(Object),而R則來自于"關系"(Relational)。幾乎所有的程序里面,都存在對象和關系數據庫。在業務邏輯層和用戶界面層中,我們是面向對象的。當對象信息發生變化的時候,我們需要把對象的信息保存在關系數據庫中。 當你開發一個應用程序的時候(不使用O/R Mapping),你可能會寫不少數據訪問層的代碼,用來從數據庫保存,刪除,讀取對象信息,等等。你在DAL中寫了很多的方法來讀取對象數據,改變狀態對象等等任務。而這些代碼寫起來總是重復的。 如果打開你最近的程序,看看DAL代碼,你肯定會看到很多近似的通用的模式。我們以保存對象的方法為例,你傳入一個對象,為SqlCommand對象添加SqlParameter,把所有屬性和對象對應,設置SqlCommand的CommandText屬性為存儲過程,然后運行SqlCommand。對于每個對象都要重復的寫這些代碼。 除此之外,還有更好的辦法嗎?有,引入一個O/R Mapping。實質上,一個O/R Mapping會為你生成DAL。與其自己寫DAL代碼,不如用O/R Mapping。你用O/R Mapping保存,刪除,讀取對象,O/R Mapping負責生成SQL,你只需要關心對象就好。 對象關系映射成功運用在不同的面向對象持久層產品中,如:Torque,OJB,hibernate,TopLink,Castor JDO, TJDO 等。
一般的ORM包括以下四部分: 一個對持久類對象進行CRUD操作的API; 一個語言或API用來規定與類和類屬性相關的查詢; 一個規定mapping metadata的工具; 一種技術可以讓ORM的實現同事務對象一起進行dirty checking, lazy association fetching以及其他的優化操作。
1 django ORM——創建表(模型)
django模型常用的字段類型
字段名 |
參數 |
意義 |
AutoField |
|
一個能夠根據可用ID自增的 IntegerField |
BooleanField |
|
一個真/假(true/false)字段 |
CharField |
(max_length) |
一個字符串字段,適用于中小長度的字符串。對于長段的文字,請使用 TextField |
CommaSeparatedIntegerField |
(max_length) |
一個用逗號分隔開的整數字段 |
DateField |
([auto_now], [auto_now_add]) |
日期字段 |
DateTimeField |
|
時間日期字段,接受跟 DateField 一樣的額外選項 |
EmailField |
|
一個能檢查值是否是有效的電子郵件地址的 CharField |
FileField |
(upload_to) |
一個文件上傳字段 |
FilePathField |
(path,[match],[recursive]) |
一個擁有若干可選項的字段,選項被限定為文件系統中某個目錄下的文件名 |
FloatField |
(max_digits,decimal_places) |
一個浮點數,對應Python中的 float 實例 |
ImageField |
(upload_to, [height_field] ,[width_field]) |
像 FileField 一樣,只不過要驗證上傳的對象是一個有效的圖片。 |
IntegerField |
|
一個整數。 |
IPAddressField |
|
一個IP地址,以字符串格式表示(例如: "24.124.1.30" )。 |
NullBooleanField |
|
就像一個 BooleanField ,但它支持 None /Null 。 |
PhoneNumberField |
|
它是一個 CharField ,并且會檢查值是否是一個合法的美式電話格式 |
PositiveIntegerField |
|
和 IntegerField 類似,但必須是正值。 |
PositiveSmallIntegerField |
|
與 PositiveIntegerField 類似,但只允許小于一定值的值,最大值取決于數據庫. |
SlugField |
|
嵌條 就是一段內容的簡短標簽,這段內容只能包含字母、數字、下 劃線或連字符。通常用于URL中 |
SmallIntegerField |
|
和 IntegerField 類似,但是只允許在一個數據庫相關的范圍內的數值(通常是-32,768到 +32,767) |
TextField |
|
一個不限長度的文字字段 |
TimeField |
|
時分秒的時間顯示。它接受的可指定參數與 DateField 和 DateTimeField 相同。 |
URLField |
|
用來存儲URL的字段。 |
USStateField |
|
美國州名稱縮寫,兩個字母。 |
XMLField |
(schema_path) |
它就是一個 TextField ,只不過要檢查值是匹配指定schema的合法XML。 |
參數名 |
意義 |
null |
如果設置為 True 的話,Django將在數據庫中存儲空值為 NULL 。默認為 False 。 |
blank |
如果是 True ,該字段允許留空,默認為 False 。 |
choices |
一個包含雙元素元組的可迭代的對象,用于給字段提供選項。 |
db_column |
當前字段在數據庫中對應的列的名字。 |
db_index |
如果為 True ,Django會在創建表格(比如運行 manage.py syncdb )時對這一列創建數據庫索引。 |
default |
字段的默認值 |
editable |
如果為 False ,這個字段在管理界面或表單里將不能編輯。默認為 True 。 |
help_text |
在管理界面表單對象里顯示在字段下面的額外幫助文本。 |
primary_key |
如果為 True ,這個字段就會成為模型的主鍵。 |
radio_admin |
默認地,對于 ForeignKey 或者擁有 choices 設置的字段,Django管理界面會使用列表選擇框(<select>)。如果 radio_admin 設置為 True 的話,Django就會使用單選按鈕界面。 |
unique |
如果是 True ,這個字段的值在整個表中必須是唯一的。 |
unique_for_date |
把它的值設成一個 DataField 或者 DateTimeField 的字段的名稱,可以確保字段在這個日期內不會出現重復值。 |
unique_for_month |
和 unique_for_date 類似,只是要求字段在指定字段的月份內唯一。 |
unique_for_year |
和 unique_for_date 及 unique_for_month 類似,只是時間范圍變成了一年。 |
verbose_name |
除 ForeignKey 、 ManyToManyField 和 OneToOneField 之外的字段都接受一個詳細名稱作為第一個位置參數。 |
實例:創建一個書籍、作者、出版社數據庫結構
一本書可能有多個作者,一個作者可以寫多本書,一本書通常僅由一個出版社出版。因此作者與書為多對多關系,出版社與書為一對多關系。接下來,我們來創建表(模型)。
多對多關系(many-to-many):彼此一對多,自動創建第三張表來表示對應關系。
一對多關系(one-to-many):主外鍵關系,在many對應的表中給需要的字段添加外鍵。
一對一(one-to-one):在一對多基礎上,在多的哪個表ForeignKey的基礎上加unique=true。
1 每個數據模型都是django.db.models.Model的子類,它的父類Model包含了所有必要的和數據庫交互的方法。并提供了一個簡介漂亮的定義數據庫字段的語法。
2 每個模型相當于單個數據庫表(多對多關系例外,會多生成一張關系表),每個屬性也是這個表中的字段。屬性名就是字段名,它的類型(例如CharField)相當于數據庫的字段類型(例如varchar)。


1 from django.db import models 2 3 # Create your models here. 4 class Publisher(models.Model): 5 6 name = models.CharField(max_length=64,verbose_name="出版社名稱") 7 city = models.CharField(max_length=24,verbose_name="所在城市") 8 9 10 def __str__(self): 11 12 return self.name 13 14 15 class Author(models.Model): 16 17 name = models.CharField(max_length=20,verbose_name="作者名稱") 18 sex = models.BooleanField(max_length=1,choices=((0,'男'),(1,'女'))) 19 email = models.EmailField() 20 birthday = models.DateField() 21 22 def __str__(self): 23 24 return self.name 25 26 27 class Book(models.Model): 28 29 title = models.CharField(max_length=64,verbose_name="書名") 30 authors = models.ManyToManyField(Author) 31 publish = models.ForeignKey(Publisher) 32 price = models.DecimalField(max_digits=5,decimal_places=2,default=10) 33 34 def __str__(self): 35 36 return self.title
確認當前app已經添加到settings設置中,然后執行數據庫初始化操作: python3 manage.py makemigrations和python3 manage.py migrate。
2 django ORM——增(create、save)
增加數據有兩種方式: (數據表中的每一條數據代表一個對象)
創建一對多關系:
創建多對多關系:
3 django ORM——刪(delete)
4 django ORM——改(update、save)
只有QuerySet對象才有update方法,因此查找行對象時只能使用filter,不能使用get。返回的整數表示受影響的行數。
save方法會將所有屬性重新設定一遍,而update只對指定的屬性值進行設定,故update方法更高效。
5 django ORM——查


1 # 查詢相關API: 2 3 # <1>filter(**kwargs): 它包含了與所給篩選條件相匹配的對象 4 5 # <2>all(): 查詢所有結果 6 7 # <3>get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,如果符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 8 9 #-----------下面的方法都是對查詢的結果再進行處理:比如 objects.filter.values()-------- 10 11 # <4>values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行后得到的并不是一系列 model的實例化對象,而是一個可迭代的字典序列 12 13 # <5>exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象 14 15 # <6>order_by(*field): 對查詢結果排序 16 17 # <7>reverse(): 對查詢結果反向排序 18 19 # <8>distinct(): 從返回結果中剔除重復紀錄 20 21 # <9>values_list(*field): 它與values()非常相似,它返回的是一個元組序列,values返回的是一個字典序列 22 23 # <10>count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。 24 25 # <11>first(): 返回第一條記錄 26 27 # <12>last(): 返回最后一條記錄 28 29 # <13>exists(): 如果QuerySet包含數據,就返回True,否則返回False。


>>> Book.objects.all() <QuerySet [<Book: python>, <Book: php>, <Book: python紅寶書>, <Book: C語言>, <Book: C++>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]> >>> Book.objects.filter(price__lt=50) <QuerySet [<Book: python紅寶書>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]> >>> Book.objects.get(title='python') <Book: python> >>> Book.objects.filter(price__lt=50).values() <QuerySet [{'title': 'python紅寶書', 'price': Decimal('8.00'), 'publish_id': 4, 'id': 3}, {'title': '杜拉拉大結局', 'price': Decimal('32.00'), 'publish_id': 3, 'id': 6}, {'title': '百年孤獨', 'price': Decimal('39.50'), 'publish_id': 4, 'id': 7}]> >>> Book.objects.filter(price__lt=50).exclude(price__gt=60) <QuerySet [<Book: python紅寶書>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]> >>> Book.objects.filter(price__lt=50).exclude(id=6) <QuerySet [<Book: python紅寶書>, <Book: 百年孤獨>]> >>> Book.objects.all().order_by('price') <QuerySet [<Book: python紅寶書>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>, <Book: C語言>, <Book: php>, <Book: python>, <Book: C++>]> >>> Book.objects.all().reverse() <QuerySet [<Book: python>, <Book: php>, <Book: python紅寶書>, <Book: C語言>, <Book: C++>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]> >>> Book.objects.all().distinct() <QuerySet [<Book: python>, <Book: php>, <Book: python紅寶書>, <Book: C語言>, <Book: C++>, <Book: 杜拉拉大結局>, <Book: 百年孤獨>]> >>> Book.objects.all().values_list() <QuerySet [(1, 'python', 1, Decimal('78.00')), (2, 'php', 2, Decimal('54.00')), (3, 'python紅寶書', 4, Decimal('8.00')), (4, 'C語言', 2, Decimal('50.00')), (5, 'C++', 1, Decimal('78.00')), (6, '杜拉拉大結局', 3, Decimal('32.00')), (7, '百年孤獨', 4, Decimal('39.50'))]> >>> Book.objects.all().count() 7 >>> Book.objects.all().first() <Book: python> >>> Book.objects.all().last() <Book: 百年孤獨> >>> Book.objects.all().exists() True
擴展查詢:


#擴展查詢,有時候DJANGO的查詢API不能方便的設置查詢條件,提供了另外的擴展查詢方法extra: #extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None (1) Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) (2) Blog.objects.extra( select=SortedDict([('a', '%s'), ('b', '%s')]), select_params=('one', 'two')) (3) q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) q = q.extra(order_by = ['-is_recent']) (4) Entry.objects.extra(where=['headline=%s'], params=['Lennon']) extra
惰性機制:
Book.objects.filter()或Book.objects.all()等只是返回一個QuerySet對象(查詢結果集對象),并不會馬上執行SQL,而是當調用QuerySet對象時才會執行SQL。
QuerySet特點:
<1>可迭代
<2>可切片
QuerySet的高效使用:


1 #<1>Django的queryset是惰性的 2 3 Django的queryset對應于數據庫的若干記錄(row),通過可選的查詢來過濾。例如,下面的代碼會得到數據庫中 4 名字為‘Dave’的所有的人: 5 person_set = Person.objects.filter(first_name="Dave") 6 7 上面的代碼并沒有運行任何的數據庫查詢。你可以使用person_set,給它加上一些過濾條件,或者將它傳給某個函數, 8 這些操作都不會發送給數據庫。這是對的,因為數據庫查詢是顯著影響web應用性能的因素之一。 9 10 #<2>要真正從數據庫獲得數據,你可以遍歷queryset或者使用if queryset,總之你用到數據時就會執行sql. 11 為了驗證這些,需要在settings里加入 LOGGING(驗證方式) 12 13 obj=models.Book.objects.filter(id=3) 14 15 # for i in obj: 16 # print(i) 17 18 # if obj: 19 # print("ok") 20 21 #<3>queryset是具有cache的 22 當你遍歷queryset時,所有匹配的記錄會從數據庫獲取,然后轉換成Django的model。這被稱為執行(evaluation). 23 這些model會保存在queryset內置的cache中,這樣如果你再次遍歷這個queryset,你不需要重復運行通用的查詢。 24 obj=models.Book.objects.filter(id=3) 25 26 # for i in obj: 27 # print(i) 28 29 # for i in obj: 30 # print(i) #LOGGING只會打印一次 31 32 33 #<4> 34 簡單的使用if語句進行判斷也會完全執行整個queryset并且把數據放入cache,雖然你并不需要這些數據! 35 為了避免這個,可以用exists()方法來檢查是否有數據: 36 37 obj = Book.objects.filter(id=4) 38 # exists()的檢查可以避免數據放入queryset的cache。 39 if obj.exists(): 40 print("hello world!") 41 42 #<5>當queryset非常巨大時,cache會成為問題 43 44 處理成千上萬的記錄時,將它們一次裝入內存是很浪費的。更糟糕的是,巨大的queryset可能會鎖住系統進程,讓你的 45 程序瀕臨崩潰。要避免在遍歷數據的同時產生queryset cache,可以使用iterator()方法來獲取數據,處理完數據就 46 將其丟棄。 47 objs = Book.objects.all() 48 # iterator()可以一次只從數據庫獲取少量數據,這樣可以節省內存 49 for obj in objs.iterator(): 50 print(obj.name) 51 當然,使用iterator()方法來防止生成cache,意味著遍歷同一個queryset時會重復執行查詢。所以使用iterator() 52 的時候要當心,確保你的代碼在操作一個大的queryset時沒有重復執行查詢 53 54 總結: 55 queryset的cache是用于減少程序對數據庫的查詢,在通常的使用下會保證只有在需要的時候才會查詢數據庫。 56 使用exists()和iterator()方法可以優化程序對內存的使用。不過,由于它們并不會生成queryset cache,可能 57 會造成額外的數據庫查詢。
對象查詢、單表條件查詢、多表條件關聯查詢:


1 #--------------------對象形式的查找-------------------------- 2 # 正向查找 3 ret1=models.Book.objects.first() 4 print(ret1.title) 5 print(ret1.price) 6 print(ret1.publisher) 7 print(ret1.publisher.name) #因為一對多的關系所以ret1.publisher是一個對象,而不是一個queryset集合 8 9 # 反向查找 10 ret2=models.Publish.objects.last() 11 print(ret2.name) 12 print(ret2.city) 13 #如何拿到與它綁定的Book對象呢? 14 print(ret2.book_set.all()) #ret2.book_set是一個queryset集合 15 16 #---------------了不起的雙下劃線(__)之單表條件查詢---------------- 17 18 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大于1 且 小于10的值 19 # 20 # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等于11、22、33的數據 21 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 22 # 23 # models.Tb1.objects.filter(name__contains="ven") 24 # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 25 # 26 # models.Tb1.objects.filter(id__range=[1, 2]) # 范圍bettwen and 27 # 28 # startswith,istartswith, endswith, iendswith, 29 30 #----------------了不起的雙下劃線(__)之多表條件關聯查詢--------------- 31 32 # 正向查找(條件) 33 34 # ret3=models.Book.objects.filter(title='Python').values('id') 35 # print(ret3)#[{'id': 1}] 36 37 #正向查找(條件)之一對多 38 39 ret4=models.Book.objects.filter(title='Python').values('publisher__city') 40 print(ret4) #[{'publisher__city': '北京'}] 41 ret5=models.Book.objects.filter(publisher__address='北京').values('publisher__name') 42 print(ret5) #[{'publisher__name': '人大出版社'}, {'publisher__name': '人大出版社'}] 43 44 #正向查找(條件)之多對多 45 ret6=models.Book.objects.filter(title='Python').values('author__name') 46 print(ret6) 47 ret7=models.Book.objects.filter(author__name="alex").values('title') 48 print(ret7) 49 50 # 反向查找(條件) 51 52 #反向查找之一對多: 53 ret8=models.Publisher.objects.filter(book__title='Python').values('name') 54 print(ret8)#[{'name': '人大出版社'}] 注意,book__title中的book就是Publisher的關聯表名 55 56 ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors') 57 print(ret9)#[{'book__authors': 1}, {'book__authors': 2}] 58 59 #反向查找之多對多: 60 ret10=models.Author.objects.filter(book__title='Python').values('name') 61 print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]
>>> Publisher.objects.filter(book__price__gt=50).values('book__title') <QuerySet [{'book__title': 'python'}, {'book__title': 'php'}, {'book__title': 'C++'}]>
聚合查詢和分組查詢:
<1> aggregate(*args,**kwargs)


from django.db.models import Avg,Min,Sum,Max 從整個查詢集生成統計值。比如,你想要計算所有在售書的平均價錢。Django的查詢語法提供了一種方式描述所有 圖書的集合。 >>> Book.objects.all().aggregate(Avg('price')) {'price__avg': 34.35} aggregate()子句的參數描述了我們想要計算的聚合值,在這個例子中,是Book模型中price字段的平均值 aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的 標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。如果你想要為聚合值指定 一個名稱,可以向聚合子句提供它: >>> Book.objects.aggregate(average_price=Avg('price')) {'average_price': 34.35} 如果你也想知道所有圖書價格的最大值和最小值,可以這樣查詢: >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
<2> annotate(*args,**kwargs)
可以通過計算查詢結果中每一個對象所關聯的對象集合,從而得出總計值(也可以是平均值或總和),即為查詢集的每一項生成聚合。
查詢alex出的書總價格
查詢各個作者出的書的總價格,這里就涉及到分組了,分組條件是authors__name
查詢各個出版社最便宜的書價是多少
F查詢和Q查詢:


1 # F 使用查詢條件的值,專門取對象中某列值的操作 2 3 # from django.db.models import F 4 # models.Tb1.objects.update(num=F('num')+1) 5 6 7 # Q 構建搜索條件 8 from django.db.models import Q 9 10 #1 Q對象(django.db.models.Q)可以對關鍵字參數進行封裝,從而更好地應用多個查詢 11 q1=models.Book.objects.filter(Q(title__startswith='P')).all() 12 print(q1)#[<Book: Python>, <Book: Perl>] 13 14 # 2、可以組合使用&,|操作符,當一個操作符是用于兩個Q的對象,它產生一個新的Q對象。 15 Q(title__startswith='P') | Q(title__startswith='J') 16 17 # 3、Q對象可以用~操作符放在前面表示否定,也可允許否定與不否定形式的組合 18 Q(title__startswith='P') | ~Q(pub_date__year=2005) 19 20 # 4、應用范圍: 21 22 # Each lookup function that takes keyword-arguments (e.g. filter(), 23 # exclude(), get()) can also be passed one or more Q objects as 24 # positional (not-named) arguments. If you provide multiple Q object 25 # arguments to a lookup function, the arguments will be “AND”ed 26 # together. For example: 27 28 Book.objects.get( 29 Q(title__startswith='P'), 30 Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) 31 ) 32 33 #sql: 34 # SELECT * from polls WHERE question LIKE 'P%' 35 # AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06') 36 37 # import datetime 38 # e=datetime.date(2005,5,6) #2005-05-06 39 40 # 5、Q對象可以與關鍵字參數查詢一起使用,不過一定要把Q對象放在關鍵字參數查詢的前面。 41 # 正確: 42 Book.objects.get( 43 Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), 44 title__startswith='P') 45 # 錯誤: 46 Book.objects.get( 47 question__startswith='P', 48 Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
原生SQL的用法:
http://www.cnblogs.com/lijintian/p/6100097.html
附錄 Django命令行工具
django-admin.py 是Django的一個用于管理任務的命令行工具,manage.py是對django-admin.py的簡單包裝,每一個Django Project里都會有一個mannage.py。
1 django-admin.py startproject project_name
創建一個新的django工程。
2 python manage.py startapp app_name
創建一個應用。
3 python manage.py runserver 8080
啟動django項目。
4 python manage.py makemigrations
migrations目錄下生成同步數據庫的腳本。
同步數據庫:python manage.py migrate
5 python manage.py createsuperuser
創建超級管理員,設置用戶名和密碼。當我們訪問http://http://127.0.0.1:8080/admin/時,便可以通過超級管理員用戶登錄了。
6 python manage.py flush
清空數據庫。
7 django-admin.py help startapp
查詢某個命令的詳細信息。
8 python manage.py shell
啟動交互界面。
9 python manage.py
查看django提供的命令。