本節內容html
1、什麼是web框架python
2、MVC和MTV視圖git
3、Django基本命令程序員
4、路由配置系統web
5、編寫視圖正則表達式
6、Templateshell
7、ORM數據庫
1、什麼是web框架 |
對於全部的web應用,本質上其實就是一個socket服務端,用戶的瀏覽器就是一個socket客戶端django
#!/usr/bin/env python #coding:utf-8 import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n") client.send("Hello, world!") def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8080)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == '__main__': main()
上述經過socket來實現了其本質,而對於真實開發中的python web程序來講,通常會分爲兩部分:服務器程序(如Apache,Nginx等)和應用程序瀏覽器
服務器程序負責對socket服務器進行封裝,並在請求到來時,對請求的各類數據進行整理。應用程序則負責具體的邏輯處理
爲了方便應用程序的開發,就出現了衆多的Web框架,例如:Django、Flask、web.py 等。
不一樣的框架有不一樣的開發方式,可是不管如何,開發出的應用程序都要和服務器程序配合,才能爲用戶提供服務。
這樣,服務器程序就須要爲不一樣的框架提供不一樣的支持。這樣混亂的局面不管對於服務器仍是框架,都是很差的。
對服務器來講,須要支持各類不一樣框架,對框架來講,只有支持它的服務器才能被開發出的應用使用。
這時候,標準化就變得尤其重要。咱們能夠設立一個標準,只要服務器程序支持這個標準,框架也支持這個標準,那麼他們就能夠配合使用。
一旦標準肯定,雙方各自實現。這樣,服務器能夠支持更多支持標準的框架,框架也可使用更多支持標準的服務器。
WSGI(Web Server Gateway Interface)是一種規範,它定義了使用python編寫的web app與web server之間接口格式,
實現web app與web server間的解耦。Python標準庫提供的獨立WSGI服務器稱爲wsgiref
from wsgiref.simple_server import make_server def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ] if __name__ == '__main__': httpd = make_server('', 8000, RunServer) print("Serving HTTP on port 8000...") httpd.serve_forever()
2、MVC和MTV模式 |
MVC模式衆所周知的模式,即:將應用程序分解成三個組成部分model(模型),view(視圖)和controller(控制器),其中:
M 管理應用程序的狀態(一般存儲到數據庫中),並約束改變狀態的行爲(或者叫作「業務規則」)
C 接收外部用戶的操做,根據操做訪問模型獲取數據,並調用「視圖」顯示這些數據,控制器就是將「模型」和「視圖」隔離,併成爲二者之間的聯繫紐帶
V 負責把數據格式化呈現給用戶
Django也是一個MVC框架,可是在Django中,控制器接收用戶輸入的部分由框架自行處理,
因此Django裏更關注的是模型(Model)、模板(Template)和視圖(View),稱爲MTV模式
Model(模型):負責業務對象和數據庫對象(ORM)
Template(模板):負責如何把頁面展現給用戶
View(視圖):負責業務邏輯,並在適當的時候調用Model和Template
此外Django還有一個URL分發器,負責將一個個URL的頁面請求分發給不一樣的view處理
3、Django基本命令 |
1. 建立一個django project
django-admin.py startproject mysite
當前目錄下會生成mysite的工程,目錄結構以下:
manage.py ----- Django項目裏面的工具,經過它能夠調用django shell和數據庫等。
settings.py ---- 包含了項目的默認設置,包括數據庫信息,調試標誌以及其餘一些工做的變量。
urls.py ----- 負責把URL模式映射到應用程序
注:若沒有成功,Windows下嘗試 django-admin startproject mysite
2. 在mysite目錄下建立應用,好比blog:
python manage.py startapp blog
3. 啓動django項目
python manage.py runserver 8080
這樣咱們的django就啓動起來了!當咱們訪問:http://127.0.0.1:8080/時就能夠看到:
四、同步更改數據庫表或字段
''' python manage.py syncdb 注意:Django 1.7.1 及以上的版本須要用如下命令 python manage.py makemigrations python manage.py migrate '''
這種方法能夠建立表,當你在models.py中新增了類時,運行它就能夠自動在數據庫中建立表了,不用手動建立
class Host(models.Model): host = models.CharField(max_length=64) port = models.IntegerField() memo = models.CharField(max_length=256, null=True) create_name = models.CharField(max_length=64) create_date = models.DateField()
5. 清空數據庫
python manage.py flush
此命令會詢問是 yes 仍是 no, 選擇 yes 會把數據所有清空掉,只留下空表
6. 建立超級管理員
''' python manage.py createsuperuser # 按照提示輸入用戶名和對應的密碼就行了郵箱能夠留空,用戶名和密碼必填 # 修改 用戶密碼能夠用: python manage.py changepassword username '''
7. Django 項目環境終端
python manage.py shell
這個命令和 直接運行 python 進入 shell 的區別是:你能夠在這個 shell 裏面調用當前項目的 models.py 中的 API,對於操做數據的測試很是方便。
8. Django 項目環境終端
python manage.py dbshell
Django 會自動進入在settings.py中設置的數據庫,若是是 MySQL 或 postgreSQL,會要求輸入數據庫用戶密碼。
在這個終端能夠執行數據庫的SQL語句。若是您對SQL比較熟悉,可能喜歡這種方式。
9. 更多命令
python manage.py
查看全部的命令,忘記子名稱的時候特別有用
4、路由配置系統(URLconf) |
URL配置本質是URL與視圖函數之間的映射表
urlpatterns = [
url(正則表達式,view視圖函數,參數,別名),
url(正則表達式,view視圖函數,參數,別名),
......
]
參數說明:
參數一:正則表達式字符串
參數二:一個可調用對象,一般爲一個視圖函數或一個指定視圖函數路徑的字符串
參數三:可選項,要傳遞給視圖函數的默認參數(字典形式),如locals()
參數四:可選項,別名
一、URLconf的正則字符串參數
1.1 簡單示例
from django.conf.urls import url from django.contrib import admin from host import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^articles/2003/$', views.special_case_2003), # 嚴格匹配 articles/2003/ url(r'^articles/[0-9]{4}/$', views.year_archive), # 嚴格匹配 articles/4位數字/ url(r'^articles/[0-9]{4}/[0-9]{2}/$', views.month_archive), # 嚴格匹配 articles/4位數字/2位數字/ # 嚴格匹配 articles/4位數字/,並將該4位數字做爲view函數的參數 url(r'^articles/([0-9]{4})/$', views.year_archive_para), ]
''' NOTE: 1 一旦匹配成功則再也不繼續 2 若要從URL 中捕獲一個值,只須要在它周圍放置一對圓括號。 3 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles。 4 每一個正則表達式前面的'r' 是可選的可是建議加上。 '''
#設置項是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑 APPEND_SLASH=True
1.2 有名分組(name group)
上面的示例使用簡單的、沒有命名的正則表達式組(經過圓括號)來捕獲URL 中的值並以位置參數傳遞給視圖
在更高級的用法中,可使用命名的正則表達式組來捕獲URL 中的值並以關鍵字 參數傳遞給視圖
在Python 正則表達式中,命名正則表達式組的語法是(?P<name>pattern),其中name 是組的名稱,pattern 是要匹配的模式
from django.conf.urls import url from django.contrib import admin from host import views urlpatterns = [ url(r'^admin/', admin.site.urls), # 嚴格匹配 articles/4位數字/2位數字/任意數字/,分爲3組,year=xxxx,month=xx,day=xxxxxx url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]+)/$', views.article_detail), ]
這個實現與前面的示例徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數。例如:
/articles/2005/03/ 請求將調用views.month_archive(request, year='2005', month='03')函數 /articles/2003/03/03/ 請求將調用函數views.article_detail(request, year='2003', month='03', day='03')。
在實際應用中,這意味你的URLconf 會更加明晰且不容易產生參數順序問題的錯誤 —— 你能夠在你的視圖函數定義中從新安排參數的順序
固然,這些好處是以簡潔爲代價;有些開發人員認爲命名組語法醜陋而繁瑣。
1.3 URLconf在什麼上查找
URLconf 在請求的URL 上查找,將它當作一個普通的Python 字符串。不包括GET和POST參數以及域名。
例如,http://www.example.com/myapp/ 請求中,URLconf 將查找myapp/。
在http://www.example.com/myapp/?page=3 請求中,URLconf 仍將查找myapp/。
URLconf 不檢查請求的方法。換句話講,全部的請求方法 —— 同一個URL的POST、GET、HEAD等等 —— 都將路由到相同的函數
1.4 捕獲的參數永遠是字符串
每一個捕獲的參數都做爲一個普通的Python 字符串傳遞給視圖,不管正則表達式使用的是什麼匹配方式。例如,下面這行URLconf 中:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
views.year_archive() 的year 參數將是一個字符串
1.5 指定視圖參數的默認值
# URLConf from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/$', views.page), url(r'^blog/page(?P<num>[0-9]+)/$', views.page), ] # View (in blog/views.py) def page(request, num="1"): ...
在上面的例子中,兩個URL模式指向同一個視圖views.page —— 可是第一個模式不會從URL 中捕獲任何值。
若是第一個模式匹配,page() 函數將使用num參數的默認值"1"。若是第二個模式匹配,page() 將使用正則表達式捕獲的num 值
1.6 其餘 URL配置
from django.conf.urls import include, url urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^host/', include('host.urls')), ]
注: include訪問url地址時,須要拼接host,如http://127.0.0.1/host/xxxx
2. 傳遞額外選項給視圖參數(瞭解)
URLconfs 具備一個鉤子,讓你傳遞一個Python 字典做爲額外的參數傳遞給視圖函數。
django.conf.urls.url() 函數能夠接收一個可選的第三個參數,它是一個字典,表示想要傳遞給視圖函數的額外關鍵字參數。
例如:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]
在這個例子中,對於/blog/2005/請求,Django 將調用views.year_archive(request, year='2005', foo='bar')。
這個技術在Syndication 框架中使用,來傳遞元數據和選項給視圖
3. 別名參數
''' urlpatterns = [ url(r'^index',views.index,name='INDEX'), ] ################### 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 'INDEX' %}" method="post"> 用戶名:<input type="text" name="username"> 密碼:<input type="password" name="password"> <input type="submit" value="submit"> </form> </body> </html> ####################### '''
5、編寫視圖 |
一個視圖函數,或者簡短來講叫作視圖,是一個簡單的Python函數,它接受web請求,而且返回web響應
響應能夠是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片. . . 是任何東西均可以
不管視圖自己包含什麼邏輯,都要返回響應
代碼寫在哪裏也無所謂,只要它在你的Python目錄下面。除此以外沒有更多的要求了——能夠說「沒有什麼神奇的地方」。
爲了可以把代碼放在某個地方,慣例是把視圖放在叫作views.py的文件中,而後把它放到你的項目或者應用目錄裏
1. 一個簡單的視圖
下面是一個返回當前日期和時間做爲HTML文檔的視圖:
from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
讓咱們逐行閱讀上面的代碼:
首先,咱們從 django.http模塊導入了HttpResponse類,以及Python的datetime庫
接着,咱們定義了current_datetime函數。它是一個視圖函數。每一個視圖函數都應接收HttpRequest對象做爲第一個參數,通常叫作request。
注意視圖函數的名稱並不重要;不須要用一個統一的命名方式來命名,以便讓Django識別它,
咱們將其命名爲current_datetime,是由於這個名稱可以精確地反映出它的功能。
這個視圖會返回一個HttpResponse對象,其中包含生成的響應。每一個視圖函數都要返回HttpResponse對象
'''
http請求-響應過程當中有兩個核心對象:
http請求對象:HttpRequest
http響應響應:HttpResponse
所在位置:django.http
'''
2. 快捷函數
2.1 render函數
---------------render(request, template_name[, context]) 結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象。 參數: request: 用於生成響應的請求對象。 template_name:要使用的模板的完整名稱,可選的參數 context:添加到模板上下文的一個字典。默認是一個空字典。若是字典中的某個值是可調用的,視圖將在渲染模板以前調用它。 content_type:生成的文檔要使用的MIME類型。默認爲DEFAULT_CONTENT_TYPE 設置的值。 status:響應的狀態碼。默認爲200。
2.2 redirect函數
頁面重定向,參數爲RUL相對地址
6、Template |
1. 模板系統介紹
HTML被直接硬編碼在 Python代碼之中,以下所示
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
儘管這種技術便於解釋視圖是如何工做的,但直接將HTML硬編碼到你的視圖裏卻並非一個好主意。 讓咱們來看一下爲何:
(1) 對頁面設計進行的任何改變都必須對 Python 代碼進行相應的修改。 站點設計的修改每每比底層 Python 代碼的修改要頻繁得多,
所以若是能夠在不進行 Python 代碼修改的狀況下變動設計,那將會方便得多
(2) Python 代碼編寫和 HTML 設計是兩項不一樣的工做,大多數專業的網站開發環境都將他們分配給不一樣的人員(甚至不一樣部門)來完成。
設計者和HTML/CSS的編碼人員不該該被要求去編輯Python的代碼來完成他們的工做
(3) 程序員編寫 Python代碼和設計人員製做模板兩項工做同時進行的效率是最高的,
遠勝於讓一我的等待另外一我的完成對某個既包含 Python又包含 HTML 的文件的編輯工做
基於這些緣由,將頁面的設計和Python的代碼分離開會更乾淨簡潔更容易維護, Django的模板系統 (Template System)實現這種模式
Python的模板:HTML代碼+邏輯控制代碼
2. 模板支持的語法
2.1 變量(使用雙大括號來引用變量)
語法格式:{{ var_name }}
----------------------------------Template和Context對象 >>> python manange.py shell (進入該django項目的環境) >>> from django.template import Context, Template >>> t = Template('My name is {{ name }}.') >>> c = Context({'name': 'Stephane'}) >>> t.render(c) 'My name is Stephane.' # 同一模板,多個上下文,一旦有了模板對象,你就能夠經過它渲染多個context,不管什麼時候咱們均可以 # 像這樣使用同一模板源渲染多個context,只進行 一次模板建立而後屢次調用render()方法渲染會 # 更爲高效: # Low for name in ('John', 'Julie', 'Pat'): t = Template('Hello, {{ name }}') print t.render(Context({'name': name})) # Good t = Template('Hello, {{ name }}') for name in ('John', 'Julie', 'Pat'): print t.render(Context({'name': name}))
Django 模板解析很是快捷。 大部分的解析工做都是在後臺經過對簡短正則表達式一次性調用來完成。
這和基於 XML 的模板引擎造成鮮明對比,那些引擎承擔了 XML 解析器的開銷,且每每比 Django 模板渲染引擎要慢上幾個數量級
from django.shortcuts import render,HttpResponse from django.template.loader import get_template #記得導入 # Create your views here. import datetime from django.template import Template,Context # def current_time(req): #原始的視圖函數 # now=datetime.datetime.now() # html="<html><body>如今時刻:<h1>%s.</h1></body></html>" %now # return HttpResponse(html) # def current_time(req): #django模板修改的視圖函數 # now=datetime.datetime.now() # t=Template('<html><body>如今時刻是:<h1 style="color:red">{{current_date}}</h1></body></html>') #t=get_template('current_datetime.html') # c=Context({'current_date':now}) # html=t.render(c) # return HttpResponse(html) #另外一種寫法(推薦) def current_time(req): now=datetime.datetime.now() return render(req, 'current_datetime.html', {'current_date':now})
2.2 深度變量的查找(萬能的句點號)
在到目前爲止的例子中,咱們經過 context 傳遞的簡單參數值主要是字符串,然而,
模板系統可以很是簡潔地處理更加複雜的數據結構,例如list、dictionary和自定義的對象。在 Django 模板中遍歷複雜數據結構的關鍵是句點字符 (.)
#最好是用幾個例子來講明一下。 # 首先,句點可用於訪問列表索引,例如: >>> from django.template import Template, Context >>> t = Template('Item 2 is {{ items.2 }}.') >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) >>> t.render(c) 'Item 2 is carrots.' #假設你要向模板傳遞一個 Python 字典。 要經過字典鍵訪問該字典的值,可以使用一個句點: >>> from django.template import Template, Context >>> person = {'name': 'Sally', 'age': '43'} >>> t = Template('{{ person.name }} is {{ person.age }} years old.') >>> c = Context({'person': person}) >>> t.render(c) 'Sally is 43 years old.' #一樣,也能夠經過句點來訪問對象的屬性。 比方說, Python 的 datetime.date 對象有 #year 、 month 和 day 幾個屬性,你一樣能夠在模板中使用句點來訪問這些屬性: >>> from django.template import Template, Context >>> import datetime >>> d = datetime.date(1993, 5, 2) >>> d.year >>> d.month >>> d.day >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') >>> c = Context({'date': d}) >>> t.render(c) 'The month is 5 and the year is 1993.' # 這個例子使用了一個自定義的類,演示了經過實例變量加一點(dots)來訪問它的屬性,這個方法適 # 用於任意的對象。 >>> from django.template import Template, Context >>> class Person(object): ... def __init__(self, first_name, last_name): ... self.first_name, self.last_name = first_name, last_name >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.') >>> c = Context({'person': Person('John', 'Smith')}) >>> t.render(c) 'Hello, John Smith.' # 點語法也能夠用來引用對象的方法。 例如,每一個 Python 字符串都有 upper() 和 isdigit() # 方法,你在模板中可使用一樣的句點語法來調用它們: >>> from django.template import Template, Context >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}') >>> t.render(Context({'var': 'hello'})) 'hello -- HELLO -- False' >>> t.render(Context({'var': '123'})) '123 -- 123 -- True' # 注意這裏調用方法時並* 沒有* 使用圓括號 並且也沒法給該方法傳遞參數;你只能調用不需參數的 # 方法。
2.3 變量的過濾器(filter)的使用
語法格式: {{obj|filter:param}}
# 1 add : 給變量加上相應的值 # # 2 addslashes : 給變量中的引號前加上斜線 # # 3 capfirst : 首字母大寫 # # 4 cut : 從字符串中移除指定的字符 # # 5 date : 格式化日期字符串 # # 6 default : 若是值是False,就替換成設置的默認值,不然就是用原本的值 # # 7 default_if_none: 若是值是None,就替換成設置的默認值,不然就使用原本的值 #實例: #value1="aBcDe" {{ value1|upper }}<br> #value2=5 {{ value2|add:3 }}<br> #value3='he llo wo r ld' {{ value3|cut:' ' }}<br> #import datetime #value4=datetime.datetime.now() {{ value4|date:'Y-m-d' }}<br> #value5=[] {{ value5|default:'空的' }}<br> #value6='<a href="#">跳轉</a>' {{ value6 }} {% autoescape off %} {{ value6 }} {% endautoescape %} {{ value6|safe }}<br> {{ value6|striptags }} #value7='1234' {{ value7|filesizeformat }}<br> {{ value7|first }}<br> {{ value7|length }}<br> {{ value7|slice:":-1" }}<br> #value8='http://www.baidu.com/?a=1&b=3' {{ value8|urlencode }}<br> value9='hello I am yuan'
2.4 標籤(tag)的使用(使用大括號和百分比的組合來使用tag)
語法格式: {% tags %}
{% if %}的使用
{% if %}標籤計算一個變量值,若是是「true」,即它存在、不爲空而且不是false的boolean值,系統則會顯示{% if %}和{% endif %}間的全部內容
{% if num >= 100 and 8 %} {% if num > 200 %} <p>num大於200</p> {% else %} <p>num大於100小於200</p> {% endif %} {% elif num < 100%} <p>num小於100</p> {% else %} <p>num等於100</p> {% endif %} {% if %} 標籤接受and,or或者not來測試多個變量值或者否認一個給定的變量 {% if %} 標籤不容許同一標籤裏同時出現and和or,不然邏輯容易產生歧義,例以下面的標籤是不合法的: {% if obj1 and obj2 or obj3 %}
{% for %}的使用
{% for %}標籤容許你按順序遍歷一個序列中的各個元素,每次循環模板系統都會渲染{% for %}和{% endfor %}之間的全部內容
<ul> {% for obj in list %} <li>{{ obj.name }}</li> {% endfor %} </ul> #在標籤裏添加reversed來反序循環列表: {% for obj in list reversed %} ... {% endfor %} #{% for %}標籤能夠嵌套: {% for country in countries %} <h1>{{ country.name }}</h1> <ul> {% for city in country.city_list %} <li>{{ city }}</li> {% endfor %} </ul> {% endfor %} #系統不支持中斷循環,系統也不支持continue語句,{% for %}標籤內置了一個forloop模板變量, #這個變量含有一些屬性能夠提供給你一些關於循環的信息 1,forloop.counter表示循環的次數,它從1開始計數,第一次循環設爲1: {% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %} 2,forloop.counter0 相似於forloop.counter,但它是從0開始計數,第一次循環設爲0 3,forloop.revcounter 4,forloop.revcounter0 5,forloop.first當第一次循環時值爲True,在特別狀況下頗有用: {% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %} # 富有魔力的forloop變量只能在循環中獲得,當模板解析器到達{% endfor %}時forloop就消失了 # 若是你的模板context已經包含一個叫forloop的變量,Django會用{% for %}標籤替代它 # Django會在for標籤的塊中覆蓋你定義的forloop變量的值 # 在其餘非循環的地方,你的forloop變量仍然可用 #{% empty %} {{li }} {% for i in li %} <li>{{ forloop.counter0 }}----{{ i }}</li> {% empty %} <li>this is empty!</li> {% endfor %} # [11, 22, 33, 44, 55] # 0----11 # 1----22 # 2----33 # 3----44 # 4----55
7、ORM |
表(模型)的建立:
實例:咱們來假定下面這些概念,字段和關係
做者模型:一個做者有姓名。
做者詳細模型:把做者的詳情放到詳情表,包含性別,email地址和出生日期,
做者詳情模型和做者模型之間是一對一的關係(one-to-one)(相似於每一個人和他的身份證之間的關係),
在大多數狀況下咱們沒有必要將他們拆分紅兩張表,這裏只是引出一對一的概念。
出版商模型:出版商有名稱,地址,所在城市,省,國家和網站。
書籍模型:書籍有書名和出版日期,一本書可能會有多個做者,一個做者也能夠寫多本書,
因此做者和書籍的關係就是多對多的關聯關係(many-to-many),一本書只應該由一個出版商出版,
因此出版商和書籍是一對多關聯關係(one-to-many),也被稱做外鍵。
1 from django.db import models<br> 2 class Publisher(models.Model): 3 name = models.CharField(max_length=30, verbose_name="名稱") 4 address = models.CharField("地址", max_length=50) 5 city = models.CharField('城市',max_length=60) 6 state_province = models.CharField(max_length=30) 7 country = models.CharField(max_length=50) 8 website = models.URLField() 9 10 class Meta: 11 verbose_name = '出版商' 12 verbose_name_plural = verbose_name 13 14 def __str__(self): 15 return self.name 16 17 class Author(models.Model): 18 name = models.CharField(max_length=30) 19 def __str__(self): 20 return self.name 21 22 class AuthorDetail(models.Model): 23 sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),)) 24 email = models.EmailField() 25 address = models.CharField(max_length=50) 26 birthday = models.DateField() 27 author = models.OneToOneField(Author) 28 29 class Book(models.Model): 30 title = models.CharField(max_length=100) 31 authors = models.ManyToManyField(Author) 32 publisher = models.ForeignKey(Publisher) 33 publication_date = models.DateField() 34 price=models.DecimalField(max_digits=5,decimal_places=2,default=10) 35 def __str__(self): 36 return self.title
-------------------------------------增(create , save) -------------------------------
from app01.models import * #create方式一: Author.objects.create(name='Alvin') *** #create方式二: Author.objects.create(**{"name":"alex"}) #save方式一: author=Author(name="alvin") author.save() #save方式二: author=Author() author.name="alvin" author.save()
-----------------------------------------刪(delete) ---------------------------------------------
>>> Book.objects.filter(id=1).delete() (3, {'app01.Book_authors': 2, 'app01.Book': 1})
咱們表面上刪除了一條信息,實際卻刪除了三條,由於咱們刪除的這本書在Book_authors表中有兩條相關信息,
這種刪除方式就是django默認的級聯刪除
-----------------------------------------改(update和save) ----------------------------------------
實例:
注意:
<1> 第二種方式修改不能用get的緣由是:update是QuerySet對象的方法,get返回的是一個model對象,它沒有update方法,
而filter返回的是一個QuerySet對象(filter裏面的條件可能有多個條件符合,好比name='alvin',可能有兩個name='alvin'的行數據)。
<2>在「插入和更新數據」小節中,咱們有提到模型的save()方法,這個方法會更新一行裏的全部列。 而某些狀況下,咱們只須要更新行裏的某幾列。
---------------------------------------查(filter,value等) -------------------------------------
# 查詢相關API: # <1>filter(**kwargs): 它包含了與所給篩選條件相匹配的對象 # <2>all(): 查詢全部結果 # <3>get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 #-----------下面的方法都是對查詢的結果再進行處理:好比 objects.filter.values()------- # <4>values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列 model的實例化對象, #而是一個可迭代的字典序列 # <5>exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象 # <6>order_by(*field): 對查詢結果排序 # <7>reverse(): 對查詢結果反向排序 # <8>distinct(): 從返回結果中剔除重複紀錄 # <9>values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 # <10>count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。 # <11>first(): 返回第一條記錄 # <12>last(): 返回最後一條記錄 # <13>exists(): 若是QuerySet包含數據,就返回True,不然返回False
---------------了不得的雙下劃線(__)之單表條件查詢---------------- # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 # # models.Tb1.objects.filter(id__range=[1, 2]) # 範圍bettwen and # # startswith,istartswith, endswith, iendswith,