返回頂部php
使用框架簡單快速開發特定的系統。html
pip freeze > requirements.txt
pip install -r requirements.txt
Django時有Python開發的一個免費的開源網站框架,能夠用於快速搭建高性能、優雅的網站。java
Django框架的特色:python
1.利用pip安裝Django。mysql
oliver@oliver-G460:~$ sudo pip3 install Django
2.利用源碼包安裝Django。linux
oliver@oliver-G460:~$ tar -zxvf django-1.10.xx.tar.gz
解壓後進入目錄,執行:git
python3 setup.py install
3.利用Linux自帶源安裝Django。web
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來管理多個開發環境。sql
方式一:用命令建立項目和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目錄文件
即urls.py文件。其本質是創建url與其所調用的視圖函數的映射關係,以此來規定訪問什麼網址去對應什麼內容,執行哪一個視圖函數。
urlpatterns = [
url(正則表達式,views視圖函數,[參數],[別名]),
]
說明(括號中四部分的意義):
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後當即返回,再也不向下查找匹配。)
?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), ]
以下所示,若是請求地址爲/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'}), ]
固定用法:
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> #######################
一個網站包含成千上萬個URL,若是全部的URL映射都放在一個文件下,極可能會出錯,也不便與維護。
所以,咱們在每一個app應用下分別建立一個urls目錄,將不一樣的請求分發給不一樣app下的urls去匹配,如:對於/blog/index/請求直接交給‘blog.urls’去處理,清晰明確,更方便管理。
http請求中產生的兩大核心對象:
http請求:HttpRequest對象
http響應:HttpResponse對象
所在位置:django.http
request就是指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
對於HttpRequest對象來講,是由django自動建立的,可是,HttpResponse對象就必須咱們本身建立。每一個view請求處理方法必須返回一個HttpResponse對象。
HttpResponse類在django.http.HttpResponse
在HttpResponse對象上擴展的經常使用方法:
頁面渲染: render()(推薦) 或 render_to_response(), 頁面跳轉: redirect("路徑") locals(): 能夠直接將函數中全部的變量傳給模板
模板由HTML+邏輯控制代碼組成。
使用雙大括號來引用變量
語法格式: {{var_name}}
渲染操做流程:
一旦建立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對象的鍵值傳遞給模板,並填充模板。
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 # 方法。
語法格式: {{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'
語法格式: {% tags %}
(1) {% if %}
(2) {% for %}
(3) {% csrf_token %}
(4) {% url %} :引用路由配置的地址
(5) {% with %} :用簡短的變量名代替複雜的變量名
(6) {% verbatim %} :禁止render
(7) {% load %} :加載標籤庫
(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 %}
將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 %}
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__,在裏面寫入:
對象-關係映射(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等於十一、2二、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 # 二、能夠組合使用&,|操做符,當一個操做符是用於兩個Q的對象,它產生一個新的Q對象。 15 Q(title__startswith='P') | Q(title__startswith='J') 16 17 # 三、Q對象能夠用~操做符放在前面表示否認,也可容許否認與不否認形式的組合 18 Q(title__startswith='P') | ~Q(pub_date__year=2005) 19 20 # 四、應用範圍: 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 # 五、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-admin.py 是Django的一個用於管理任務的命令行工具,manage.py是對django-admin.py的簡單包裝,每個Django Project裏都會有一個mannage.py。
建立一個新的django工程。
建立一個應用。
啓動django項目。
migrations目錄下生成同步數據庫的腳本。
同步數據庫:python manage.py migrate
建立超級管理員,設置用戶名和密碼。當咱們訪問http://http://127.0.0.1:8080/admin/時,即可以經過超級管理員用戶登陸了。
清空數據庫。
查詢某個命令的詳細信息。
啓動交互界面。
查看django提供的命令。