框架,即framework,特指爲解決一個開放性問題而設計的具備必定約束性的支撐結構,使用框架能夠幫你快速開發特定的系統,簡單地說,就是你用別人搭建好的舞臺來作表演。css
對於全部的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端html
import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8")) client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8")) def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8001)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == '__main__': main()
最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。前端
若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。python
正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口,讓咱們專心用Python編寫Web業務。jquery
這個接口就是WSGI:Web Server Gateway Interface。nginx
-----------------------------模擬框架實現功能---------------------------git
所需的HTML代碼自行添加 from wsgiref.simple_server import make_server import time def yhr(req): f = open("index2.html","rb") data = f.read() return data def login(req): print(req["QUERY_STRING"]) return b"welcome !" def singup(req): pass def show_time(req): times =time.ctime() # return ("<h1>time:%s</h1>"%str(times)).encode("utf8") f = open("show_time.html","rb") data = f.read() data = data.decode("utf8") data = data.replace("{{time}}",str(times)) return data.encode("utf8") def router(): url_patterns = [ ("/login",login), ("/singup",singup), ("/yhr",yhr), ("/show_time",show_time) ] return url_patterns def application(environ, start_response): print("path",environ["PATH_INFO"]) path = environ["PATH_INFO"] # 取數據 start_response('200 OK', [('Content-Type', 'text/html')]) url_patterns = router() func = None for item in url_patterns: if item[0] == path: func = item[1] break if func: return [func(environ)] else: return [b"404"] httpd = make_server('', 8000, application) print('Serving HTTP on port 8000...') # 開始監聽HTTP請求: httpd.serve_forever()
著名的MVC模式:所謂MVC就是把web應用分爲模型(M),控制器(C),視圖(V)三層;他們之間以一種插件似的,鬆耦合的方式鏈接在一塊兒。web
模型負責業務對象與數據庫的對象(ORM),視圖負責與用戶的交互(頁面),控制器(C)接受用戶的輸入調用模型和視圖完成用戶的請求。正則表達式
Django的MTV模式本質上與MVC模式沒有什麼差異,也是各組件之間爲了保持鬆耦合關係,只是定義上有些許不一樣,Django的MTV分別表明:sql
Model(模型):負責業務對象與數據庫的對象(ORM)
Template(模版):負責如何把頁面展現給用戶
View(視圖):負責業務邏輯,並在適當的時候調用Model和Template
此外,Django還有一個url分發器,它的做用是將一個個URL的頁面請求分發給不一樣的view處理,view再調用相應的Model和Template
django #安裝: pip3 install django 添加環境變量 :在安裝Python3的lib---》site.packages---》django---》bin #1 建立project django-admin startproject mysite ---mysite ---settings.py ---url.py ---wsgi.py ---- manage.py(啓動文件) #2 建立APP python mannage.py startapp app01 #3 settings配置 TEMPLATES STATICFILES_DIRS=( os.path.join(BASE_DIR,"statics"), ) STATIC_URL = '/static/' # 咱們只能用 STATIC_URL,但STATIC_URL會按着你的STATICFILES_DIRS去找#4 根據需求設計代碼 url.py view.py #5 使用模版 render(req,"index.html") #6 啓動項目 python manage.py runserver 127.0.0.1:8090 #7 鏈接數據庫,操做數據 model.py
django-admin.py 是Django的一個用於管理任務的命令行工具,manage.py是對django-admin.py的簡單包裝,每個Django Project裏都會有一個mannage.py。
<1> 建立一個django工程 : django-admin.py startproject mysite
當前目錄下會生成mysite的工程,目錄結構以下:
<2>在mysite目錄下建立blog應用: python manage.py startapp blog
<3>啓動django項目:python manage.py runserver 8080
這樣咱們的django就啓動起來了!當咱們訪問:http://127.0.0.1:8080/時就能夠看到:
<4>生成同步數據庫的腳本:python manage.py makemigrations
同步數據庫: python manage.py migrate
注意:在開發過程當中,數據庫同步誤操做以後,不免會遇到後面不能同步成功的狀況,解決這個問題的一個簡單粗暴方法是把migrations目錄下
的腳本(除__init__.py以外)所有刪掉,再把數據庫刪掉以後建立一個新的數據庫,數據庫同步操做再從新作一遍。
<5>當咱們訪問http://127.0.0.1:8080/admin/時,會出現:
因此咱們須要爲進入這個項目的後臺建立超級管理員:python manage.py createsuperuser,設置好用戶名和密碼後即可登陸啦!
<6>清空數據庫:python manage.py flush
<7>查詢某個命令的詳細信息: django-admin.py help startapp
admin 是Django 自帶的一個後臺數據庫管理系統。
<8>啓動交互界面 :python manage.py shell
這個命令和直接運行 python 進入 shell 的區別是:你能夠在這個 shell 裏面調用當前項目的 models.py 中的 API,對於操做數據,還有一些小測試很是方便。
<9> 終端上輸入python manage.py 能夠看到詳細的列表,在忘記子名稱的時候特別有用。
1 1、概述: 2 3 #靜態文件交由Web服務器處理,Django自己不處理靜態文件。簡單的處理邏輯以下(以nginx爲例): 4 5 # URI請求-----> 按照Web服務器裏面的配置規則先處理,以nginx爲例,主要求配置在nginx. 6 #conf裏的location 7 8 |---------->若是是靜態文件,則由nginx直接處理 9 10 |---------->若是不是則交由Django處理,Django根據urls.py裏面的規則進行匹配 11 12 # 以上是部署到Web服務器後的處理方式,爲了便於開發,Django提供了在開發環境的對靜態文件的處理機制,方法是這樣: 13 14 #1、在INSTALLED_APPS裏面加入'django.contrib.staticfiles', 15 16 #2、在urls.py裏面加入 17 if settings.DEBUG: 18 urlpatterns += patterns('', url(r'^media/(?P<path>.*)$', 19 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }), 20 url(r'^static/(?P<path>.*)$', 21 'django.views.static.serve',{'document_root':settings.STATIC_ROOT}), ) 22 23 # 3、這樣就能夠在開發階段直接使用靜態文件了。 24 25 2、MEDIA_ROOT和MEDIA_URL 26 27 #而靜態文件的處理又包括STATIC和MEDIA兩類,這每每容易混淆,在Django裏面是這樣定義的: 28 29 #MEDIA:指用戶上傳的文件,好比在Model裏面的FileFIeld,ImageField上傳的文件。若是你定義 30 31 #MEDIA_ROOT=c:\temp\media,那麼File=models.FileField(upload_to="abc/")#,上傳的文件就會被保存到c:\temp\media\abc 32 #eg: 33 class blog(models.Model): 34 Title=models.charField(max_length=64) 35 Photo=models.ImageField(upload_to="photo") 36 # 上傳的圖片就上傳到c:\temp\media\photo,而在模板中要顯示該文件,則在這樣寫 37 #在settings裏面設置的MEDIA_ROOT必須是本地路徑的絕對路徑,通常是這樣寫: 38 BASE_DIR= os.path.abspath(os.path.dirname(__file__)) 39 MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\\','/') 40 41 #MEDIA_URL是指從瀏覽器訪問時的地址前綴,舉個例子: 42 MEDIA_ROOT=c:\temp\media\photo 43 MEDIA_URL="/data/" 44 #在開發階段,media的處理由django處理: 45 46 # 訪問http://localhost/data/abc/a.png就是訪問c:\temp\media\photo\abc\a.png 47 48 # 在模板裏面這樣寫<img src="{{MEDIA_URL}}abc/a.png"> 49 50 # 在部署階段最大的不一樣在於你必須讓web服務器來處理media文件,所以你必須在web服務器中配置, 51 # 以便能讓web服務器能訪問media文件 52 # 以nginx爲例,能夠在nginx.conf裏面這樣: 53 54 location ~/media/{ 55 root/temp/ 56 break; 57 } 58 59 # 具體能夠參考如何在nginx部署django的資料。 60 61 3、STATIC_ROOT和STATIC_URL、 62 STATIC主要指的是如css,js,images這樣文件,在settings裏面能夠配置STATIC_ROOT和STATIC_URL, 63 配置方式與MEDIA_ROOT是同樣的,可是要注意 64 65 #STATIC文件通常保存在如下位置: 66 67 #1、STATIC_ROOT:在settings裏面設置,通常用來放一些公共的js,css,images等。 68 69 #2、app的static文件夾,在每一個app所在文夾都可以創建一個static文件夾,而後當運行collectstatic時, 70 # Django會遍歷INSTALL_APPS裏面全部app的static文件夾,將裏面全部的文件複製到STATIC_ROOT。所以, 71 # 若是你要創建可複用的app,那麼你要將該app所須要的靜態文件放在static文件夾中。 72 73 # 也就是說一個項目引用了不少app,那麼這個項目所須要的css,images等靜態文件是分散在各個app的static文件的,比 74 # 較典型的是admin應用。當你要發佈時,須要將這些分散的static文件收集到一個地方就是STATIC_ROOT。 75 76 #3、STATIC文件還能夠配置STATICFILES_DIRS,指定額外的靜態文件存儲位置。 77 # STATIC_URL的含義與MEDIA_URL相似。 78 79 # ---------------------------------------------------------------------------- 80 #注意1: 81 #爲了後端的更改不會影響前端的引入,避免形成前端大量修改 82 83 STATIC_URL = '/static/' #引用名 84 STATICFILES_DIRS = ( 85 os.path.join(BASE_DIR,"statics") #實際名 ,即實際文件夾的名字 86 ) 87 88 #django對引用名和實際名進行映射,引用時,只能按照引用名來,不能按實際名去找 89 #<script src="/statics/jquery-3.1.1.js"></script> 90 #------error-----不能直接用,必須用STATIC_URL = '/static/': 91 #<script src="/static/jquery-3.1.1.js"></script> 92 93 #注意2(statics文件夾寫在不一樣的app下,靜態文件的調用): 94 95 STATIC_URL = '/static/' 96 97 STATICFILES_DIRS=( 98 ('hello',os.path.join(BASE_DIR,"app01","statics")) , 99 ) 100 101 #<script src="/static/hello/jquery-1.8.2.min.js"></script> 102 103 #注意3: 104 STATIC_URL = '/static/' 105 {% load staticfiles %} 106 # <script src={% static "jquery-1.8.2.min.js" %}></script>
其它重要參數設置:
1 APPEND_SLASH 2 Default: True 3 When set to True, if the request URL does not match any of the patterns in the URLconf and it 4 doesn’t end in a slash, an HTTP redirect is issued to the same URL with a slash appended. Note 5 that the redirect may cause any data submitted in a POST request to be lost.
URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL模式以及要爲該URL模式調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。
urlpatterns = [ url(正則表達式, views視圖函數,參數,別名), ]
參數說明:
例如:url(r'student', views.student,{"time:t"},name="stu"),
1 from django.conf.urls import url 2 from django.contrib import admin 3 4 from app01 import views 5 6 urlpatterns = [ 7 8 url(r'^articles/2003/$', views.special_case_2003), 9 10 #url(r'^articles/[0-9]{4}/$', views.year_archive), 11 12 url(r'^articles/([0-9]{4})/$', views.year_archive), #no_named group 13 14 url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), 15 16 url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), 17 18 ]
上面的例子中使用簡單,non-named正則表達式組(經過括號)捕捉到的URL,將他們做爲一個視圖的位置參數。在更高級的用法,可使用指定的正則表達式組捕獲的URL部分並將它們做爲關鍵字參數傳遞給一個視圖。
在Python中正則表達式,指定的正則表達式的語法組(? P <名稱>模式),在那裏的名字是集團的名稱和模式是模式匹配。
這是上面的例子URLconf,重寫使用命名組:
1 import re 2 3 ret=re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo') 4 5 print(ret.group()) 6 print(ret.group('id')) 7 print(ret.group('name'))
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),
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),
]
這完成了前面的例子同樣,有一個微妙的差別:捕獲的值傳遞給視圖函數做爲關鍵字參數而不是位置參數。
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'}), ]
在本例中,請求/博客/ 2005 / Django將調用視圖。year_archive(請求,年= ' 2005 ',foo = '酒吧')。
這種技術用於聚合框架經過元數據和視圖選項。
處理衝突
能夠有一個URL模式捕獲關鍵字參數,並經過參數具備相同名字的字典的額外參數。當這種狀況發生時,在字典裏的參數將用來替代參數捕獲的URL。
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), ] ################### views視圖函數 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') ##################### templates裏面的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> #######################
#At any point, your urlpatterns can 「include」 other URLconf modules. This #essentially 「roots」 a set of URLs below other ones. #For example, here’s an excerpt of the URLconf for the Django website itself. #It includes a number of other URLconfs: from django.conf.urls import include, url urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^blog/', include('blog.urls')), ]
http請求中產生兩個核心對象:
http請求:HttpRequest對象
http響應:HttpResponse對象
所在位置:django.http
以前咱們用到的參數request就是HttpRequest 檢測方法:isinstance(request,HttpRequest)
# path: 請求頁面的全路徑,不包括域名 # # method: 請求中使用的HTTP方法的字符串表示。全大寫表示。例如 # # if req.method=="GET": # # do_something() # # elseif req.method=="POST": # # do_something_else() # # GET: 包含全部HTTP GET參數的類字典對象 # # POST: 包含全部HTTP POST參數的類字典對象 # # 服務器收到空的POST請求的狀況也是可能發生的,也就是說,表單form經過 # HTTP POST方法提交請求,可是表單中可能沒有數據,所以不能使用 # if request.POST來判斷是否使用了HTTP POST 方法;應該使用 if request.method=="POST" # # # # COOKIES: 包含全部cookies的標準Python字典對象;keys和values都是字符串。 # # FILES: 包含全部上傳文件的類字典對象;FILES中的每個Key都是<input type="file" name="" />
標籤中 name屬性的值,FILES中的每個value同時也是一個標準的python字典對象,包含下面三個Keys: # # filename: 上傳文件名,用字符串表示 # content_type: 上傳文件的Content Type # content: 上傳文件的原始內容 # # # user: 是一個django.contrib.auth.models.User對象,表明當前登錄的用戶。若是訪問用戶當前 # 沒有登錄,user將被初始化爲django.contrib.auth.models.AnonymousUser的實例。你 # 能夠經過user的is_authenticated()方法來辨別用戶是否登錄: # if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware # 時該屬性纔可用 # # session: 惟一可讀寫的屬性,表明當前會話的字典對象;本身有激活Django中的session支持時該屬性纔可用。 #方法 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(request,「HTML」)(推薦)<br> render_to_response(), 頁面跳轉: redirect("路徑") locals(): 能夠直接將函數中全部的變量傳給模板
模板系統的組成:HTML代碼和邏輯控制代碼
邏輯控制代碼能夠理解是django模板語言
變量(使用雙大括號來引用變量):
語法
1 {{var_name}} 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}) 推薦方式
------深度變量的查找(萬能的句點號)
在到目前爲止的例子中,咱們經過 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 1993 >>> d.month 5 >>> d.day 2 >>> 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' # 注意這裏調用方法時並* 沒有* 使用圓括號 並且也沒法給該方法傳遞參數;你只能調用不需參數的 # 方法。
變量的過濾器(filter)的使用
語法格式
{{var|filter:param}}
管道符號後面的功能,好比{{ var|length }},求變量長度的 length 就是一個過濾器。
經常使用的過濾器
1.add : 給變量加上相應的值 2 addslashes : 給變量中的引號前加上斜線 3 capfirst : 首字母大寫 4 cut : 從字符串中移除指定的字符 5 date : 格式化日期字符串 6 default : 若是值是False,就替換成設置的默認值,不然就是用原本的值 7 default_if_none: 若是值是None,就替換成設置的默認值,不然就使用原本的值
語法格式
{% tags %}
{% if %} 的使用
{% if %} 和 {% endif %}要成對
{% 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 %}
{% for %}不支持中斷循環,也不支持continue語句
{% for %}關於循環其餘用法
forloop.counter表示循環的次數,它從1開始計數,第一次循環設爲1: forloop.counter0 索引從 0 開始算 forloop.revcounter表示循環中剩下的items數量,第一次循環時設爲items總數,最後一次設爲1 forloop.revcounter0表示`items總數少一個,最後一次循環設置爲0 forloop.first表示當第一次循環時值爲True,在特別狀況下頗有用: forloop.last表示當最後一次循環時值爲True forloop.parentioop表示在嵌套循環中表示父級循環的forloop
富有魔力的forloop變量只能在循環中獲得,當模板解析器到達{% endfor %}時forloop就消失了
若是你的模板context已經包含一個叫forloop的變量,Django會用{% for %}標籤替代它
Django會在for標籤的塊中覆蓋你定義的forloop變量的值
在其餘非循環的地方,你的forloop變量仍然可用
{% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %} 表示循環的次數,它從1開始計數,第一次循環設爲1:
{%csrf_token%}:csrf_token標籤
用於生成csrf_token的標籤,用於防治跨站攻擊驗證。注意若是你在view的index裏用的是render_to_response方法,不會生效
{% url %}: 引用路由配置的地址
<form action="{% url "路由別名"%}" > <input type="text"> <input type="submit"value="提交"> {%csrf_token%} </form>
{% with %}:用更簡單的變量名替代複雜的變量名
{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %} 基本不多起復雜變量名,通常起變量名都要特變形象
{% verbatim %}: 禁止render渲染
{% verbatim %} {{ hello }} {% endverbatim % 若是想要{{hello}}在網頁正常顯示出來,則用這個
{% load %}: 加載標籤庫
靜態文件的引入方式用過
{% load staticfiles %}
後面引入其餘的標籤庫在一一列出
咱們自定義過濾器和簡單的標籤咱們須要
#!/usr/bin/env python #-*- coding:utf-8 -*- from django import template from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改變 @register.filter def filter_multi(x,y): return x*y @register.simple_tag def simple_tag_multi(x,y): return x*y @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg) return mark_safe(result)
在使用自定義simple_tag和filter的html文件中導入以前建立的 my_tags.py :{% load my_tags %}
在settings中的INSTALLED_APPS配置當前app,否則django沒法找到自定義的simple_tag.
{% load my_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ num|filter_multi:2 }} #24 <br>
{{ num|filter_multi:"[22,333,4444]" }}<br>
<p>{% simple_tag_multi 2 5 %} 參數不限,但不能放在if for語句中 </p>
{% simple_tag_multi num 5 %}
</body>
</html>
視圖和路由的配置文件
#路由 from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',views.index), ] #視圖 from django.shortcuts import render,HttpResponse # Create your views here. def index(request): num=12 return render(request,"index.html",locals())
注:filter能夠用在if等語句後,simple_tag不能夠
{% include %}該標籤容許在(模板中)包含其它的模板的內容。 標籤的參數是所要包含的模板名稱,能夠是一個變量,也能夠是用單/雙引號硬編碼的字符串。 每當在多個模板中出現相同的代碼時,就應該考慮是否要使用 {% include %} 來減小重複。
引入方法
{% load staticfiles %} HTML相關內容 {% include '要引入的html文件名' %}
常見的 Web 開發問題: 在整個網站中,如何減小共用頁面區域(好比站點導航)所引發的重複和冗餘代碼?
解決該問題的傳統作法是使用 服務器端的 includes ,你能夠在 HTML 頁面中使用該指令將一個網頁嵌入到另外一箇中。 事實上, Django 經過剛纔講述的 {% include %} 支持了這種方法。 可是用 Django 解決此類問題的首選方法是使用更加優雅的策略—— 模板繼承 。
本質上來講,模板繼承就是先構造一個基礎框架模板,然後在其子模板中對它所包含站點公用部分和定義塊進行重載
若是子板不自定義塊,默認會繼承母板的全部內容(包括模板的css,js),若是子板要修改css或js文件,在相應地方加塊,就能夠了
例如:
簡單寫一個子板繼承母板
定義母板文件base.html,定義子板要自定義的塊
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <H1> HAHA </H1> {% block content %} <h2>子板自定義修改的內容</h2> {% endblock %} </body> </html>
定義子板文件child.html
{% extends "base.html" %}
子板若是就這麼一行代碼,就會繼承母板的全部內容,這{% extends "母板文件" %}必須寫在最首行
若是要自定義修改塊
{% extends "base.html" %} {% block content %} <h2 style="color: red">我是子板,修改了母板自定義塊的內容</h2> {% endblock %}
注:
母板
{% block 自定義塊名%}
子板的塊
{% block 母板中相應設置的塊名 }
{% block %} 內容 {% endblock %}的標籤也是成對出現
一、基本建立
Django提供了一個抽象層("Model")的構建和管理Web應用程序的數據。
Django使用一種新的方式,即:關係對象映射(Object Relational Mapping,簡稱ORM)。
django.db.models.model
# DEMO class Student(models.Model): name = models.CharField(max_length=10) sex = models.CharField(max_length=10) age = models.IntegerField() grade = models.ForeignKey('Grade')
1 AutoField(Field) 2 - int自增列,必須填入參數 primary_key=True 3 4 BigAutoField(AutoField) 5 - bigint自增列,必須填入參數 primary_key=True 6 7 注:當model中若是沒有自增列,則自動會建立一個列名爲id的列 8 from django.db import models 9 10 class UserInfo(models.Model): 11 # 自動建立一個列名爲id的且爲自增的整數列 12 username = models.CharField(max_length=32) 13 14 class Group(models.Model): 15 # 自定義自增列 16 nid = models.AutoField(primary_key=True) 17 name = models.CharField(max_length=32) 18 19 SmallIntegerField(IntegerField): 20 - 小整數 -32768 ~ 32767 21 22 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 23 - 正小整數 0 ~ 32767 24 IntegerField(Field) 25 - 整數列(有符號的) -2147483648 ~ 2147483647 26 27 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 28 - 正整數 0 ~ 2147483647 29 30 BigIntegerField(IntegerField): 31 - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807 32 33 自定義無符號整數字段 34 35 class UnsignedIntegerField(models.IntegerField): 36 def db_type(self, connection): 37 return 'integer UNSIGNED' 38 39 PS: 返回值爲字段在數據庫中的屬性,Django字段默認的值爲: 40 'AutoField': 'integer AUTO_INCREMENT', 41 'BigAutoField': 'bigint AUTO_INCREMENT', 42 'BinaryField': 'longblob', 43 'BooleanField': 'bool', 44 'CharField': 'varchar(%(max_length)s)', 45 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 46 'DateField': 'date', 47 'DateTimeField': 'datetime', 48 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 49 'DurationField': 'bigint', 50 'FileField': 'varchar(%(max_length)s)', 51 'FilePathField': 'varchar(%(max_length)s)', 52 'FloatField': 'double precision', 53 'IntegerField': 'integer', 54 'BigIntegerField': 'bigint', 55 'IPAddressField': 'char(15)', 56 'GenericIPAddressField': 'char(39)', 57 'NullBooleanField': 'bool', 58 'OneToOneField': 'integer', 59 'PositiveIntegerField': 'integer UNSIGNED', 60 'PositiveSmallIntegerField': 'smallint UNSIGNED', 61 'SlugField': 'varchar(%(max_length)s)', 62 'SmallIntegerField': 'smallint', 63 'TextField': 'longtext', 64 'TimeField': 'time', 65 'UUIDField': 'char(32)', 66 67 BooleanField(Field) 68 - 布爾值類型 69 70 NullBooleanField(Field): 71 - 能夠爲空的布爾值 72 73 CharField(Field) 74 - 字符類型 75 - 必須提供max_length參數, max_length表示字符長度 76 77 TextField(Field) 78 - 文本類型 79 80 EmailField(CharField): 81 - 字符串類型,Django Admin以及ModelForm中提供驗證機制 82 83 IPAddressField(Field) 84 - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制 85 86 GenericIPAddressField(Field) 87 - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6 88 - 參數: 89 protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6" 90 unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓刺功能,須要protocol="both" 91 92 URLField(CharField) 93 - 字符串類型,Django Admin以及ModelForm中提供驗證 URL 94 95 SlugField(CharField) 96 - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號) 97 98 CommaSeparatedIntegerField(CharField) 99 - 字符串類型,格式必須爲逗號分割的數字 100 101 UUIDField(Field) 102 - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證 103 104 FilePathField(Field) 105 - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能 106 - 參數: 107 path, 文件夾路徑 108 match=None, 正則匹配 109 recursive=False, 遞歸下面的文件夾 110 allow_files=True, 容許文件 111 allow_folders=False, 容許文件夾 112 113 FileField(Field) 114 - 字符串,路徑保存在數據庫,文件上傳到指定目錄 115 - 參數: 116 upload_to = "" 上傳文件的保存路徑 117 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage 118 119 ImageField(FileField) 120 - 字符串,路徑保存在數據庫,文件上傳到指定目錄 121 - 參數: 122 upload_to = "" 上傳文件的保存路徑 123 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage 124 width_field=None, 上傳圖片的高度保存的數據庫字段名(字符串) 125 height_field=None 上傳圖片的寬度保存的數據庫字段名(字符串) 126 127 DateTimeField(DateField) 128 - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 129 130 DateField(DateTimeCheckMixin, Field) 131 - 日期格式 YYYY-MM-DD 132 133 TimeField(DateTimeCheckMixin, Field) 134 - 時間格式 HH:MM[:ss[.uuuuuu]] 135 136 DurationField(Field) 137 - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型 138 139 FloatField(Field) 140 - 浮點型 141 142 DecimalField(Field) 143 - 10進制小數 144 - 參數: 145 max_digits,小數總長度 146 decimal_places,小數位長度 147 148 BinaryField(Field) 149 - 二進制類 150 151 字段
1 null 數據庫中字段是否能夠爲空 2 db_column 數據庫中字段的列名 3 db_tablespace 4 default 數據庫中字段的默認值 5 primary_key 數據庫中字段是否爲主鍵 6 db_index 數據庫中字段是否能夠創建索引 7 unique 數據庫中字段是否能夠創建惟一索引 8 unique_for_date 數據庫中字段【日期】部分是否能夠創建惟一索引 9 unique_for_month 數據庫中字段【月】部分是否能夠創建惟一索引 10 unique_for_year 數據庫中字段【年】部分是否能夠創建惟一索引 11 12 verbose_name Admin中顯示的字段名稱 13 blank Admin中是否容許用戶輸入爲空 14 editable Admin中是否能夠編輯 15 help_text Admin中該字段的提示信息 16 choices Admin中顯示選擇框的內容,用不變更的數據放在內存中從而避免跨表操做 17 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) 18 19 error_messages 自定義錯誤信息(字典類型),從而定製想要顯示的錯誤信息; 20 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 21 如:{'null': "不能爲空.", 'invalid': '格式錯誤'} 22 23 validators 自定義錯誤驗證(列表類型),從而定製想要的驗證規則 24 from django.core.validators import RegexValidator 25 from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ 26 MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 27 如: 28 test = models.CharField( 29 max_length=32, 30 error_messages={ 31 'c1': '優先錯信息1', 32 'c2': '優先錯信息2', 33 'c3': '優先錯信息3', 34 }, 35 validators=[ 36 RegexValidator(regex='root_\d+', message='錯誤了', code='c1'), 37 RegexValidator(regex='root_112233\d+', message='又錯誤了', code='c2'), 38 EmailValidator(message='又錯誤了', code='c3'), ] 39 ) 40 41 參數 42 43 Field參數
二、連表結構例如在建表的時候應該瞭解到如何
應用場景:
三、表操做
a、基本操做
# 增 # # models.Tb1.objects.create(c1='xx', c2='oo') 增長一條數據,能夠接受字典類型數據 **kwargs # obj = models.Tb1(c1='xx', c2='oo') # obj.save() # 查 # # models.Tb1.objects.get(id=123) # 獲取單條數據,不存在則報錯(不建議) # models.Tb1.objects.all() # 獲取所有 # models.Tb1.objects.filter(name='seven')# 獲取指定條件的數據 # 刪 # # models.Tb1.objects.filter(name='seven').delete() # 刪除指定條件的數據 # 改 # models.Tb1.objects.filter(name='seven').update(gender='0') # 將指定條件的數據更新,均支持 **kwargs # obj = models.Tb1.objects.get(id=1) # obj.c1 = '111' # obj.save()
b、進階操做(了不得的雙下劃線)
# 獲取個數 # # models.Tb1.objects.filter(name='seven').count() # 大於,小於 # # models.Tb1.objects.filter(id__gt=1) # 獲取id大於1的值 # models.Tb1.objects.filter(id__gte=1) # 獲取id大於等於1的值 # models.Tb1.objects.filter(id__lt=10) # 獲取id小於10的值 # models.Tb1.objects.filter(id__lte=10) # 獲取id小於10的值 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 # in # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # isnull # Entry.objects.filter(pub_date__isnull=True) # contains # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 # models.Tb1.objects.exclude(name__icontains="ven") # range # # models.Tb1.objects.filter(id__range=[1, 2]) # 範圍bettwen and # 其餘相似 # # startswith,istartswith, endswith, iendswith, # order by # # models.Tb1.objects.filter(name='seven').order_by('id') # asc # models.Tb1.objects.filter(name='seven').order_by('-id') # desc # group by # # from django.db.models import Count, Min, Max, Sum # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" # limit 、offset # # models.Tb1.objects.all()[10:20] # regex正則匹配,iregex 不區分大小寫 # # Entry.objects.get(title__regex=r'^(An?|The) +') # Entry.objects.get(title__iregex=r'^(an?|the) +') # date # # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) # year # # Entry.objects.filter(pub_date__year=2005) # Entry.objects.filter(pub_date__year__gte=2005) # month # # Entry.objects.filter(pub_date__month=12) # Entry.objects.filter(pub_date__month__gte=6) # day # # Entry.objects.filter(pub_date__day=3) # Entry.objects.filter(pub_date__day__gte=3) # week_day # # Entry.objects.filter(pub_date__week_day=2) # Entry.objects.filter(pub_date__week_day__gte=2) # hour # # Event.objects.filter(timestamp__hour=23) # Event.objects.filter(time__hour=5) # Event.objects.filter(timestamp__hour__gte=12) # minute # # Event.objects.filter(timestamp__minute=29) # Event.objects.filter(time__minute=46) # Event.objects.filter(timestamp__minute__gte=29) # second # # Event.objects.filter(timestamp__second=31) # Event.objects.filter(time__second=2) # Event.objects.filter(timestamp__second__gte=31)
c、連表操做(了不得的雙下劃線)
1 # DEMO 2 # 班級和老師存在多對多關係、班級和學生存在一對多關係 3 from django.db import models 4 5 class Classes(models.Model): 6 titile = models.CharField(max_length=32) 7 m = models.ManyToManyField('Teachers') 8 9 10 class Teachers(models.Model): 11 name = models.CharField (max_length=32) 12 13 14 class Student(models.Model): 15 username = models.CharField(max_length=32) 16 age = models.IntegerField() 17 gender = models.BooleanField() 18 cs = models.ForeignKey(Classes)
1 # 增 2 # Teachers.objects.create(name='root') 3 # obj = Teachers(name='root') 4 # obj.save() 5 # 查 6 # Teachers.objects.all() 7 # Teachers.objects.filter(id=1) 8 # Teachers.objects.filter(id=1,name='root') 9 # result = Teachers.objects.filter(id__gt=1) 10 # [obj(id,name),] 11 # result = Teachers.objects.filter(id__gt=1).first() 12 # 刪 13 # Teachers.objects.filter(id=1).delete() 14 # 改 15 # Teachers.objects.all().update(name='alex') 16 # Teachers.objects.filter(id=1).update(name='alex')
1 # 增長 2 # Student.objects.create(username='東北',age=18,gender='男',cs_id=1) 3 # Student.objects.create(username='東北',age=18,gender='男',cs= Classes.objects.filter(id=1).first() ) 4 # 查看 5 """ 6 ret = Student.objects.all() 7 # [] 8 # [ obj(..),] 9 # [ obj(1 東北 18 男 1),obj(2 東北1 118 男 2),obj(..),] 10 for item in ret: 11 print(item.id) 12 print(item.username) 13 print(item.age) 14 print(item.gender) 15 print(item.cs_id) 16 print(item.cs.id) 17 print(item.cs.name) 18 """ 19 # 刪除 20 # Student.objects.filter(id=1).delete() 21 # Student.objects.filter(cs_id=1).delete() 22 23 # cid = input('請輸入班級ID') 24 # Student.objects.filter(cs_id=cid).delete() 25 26 # cname = input('請輸入班級名稱') 27 # Student.objects.filter(cs_id=cid).delete() 28 # Student.objects.filter(cs__name=cname).delete()
1 """ 2 班級: 3 id title 4 1 3班 5 2 4班 6 3 5班 7 老師: 8 id title 9 1 Alex 10 2 老妖 11 3 瞎驢 12 4 Eric 13 老師班級關係表(類): 14 id 班級id 老師id 15 1 1 2 16 2 1 3 17 4 2 2 18 5 2 3 19 6 2 4 20 7 1 5 21 22 23 # 增 24 obj = Classes.objects.filter(id=1).first() #1 3班 25 obj.m.add(2) 26 obj.m.add([4,3]) 27 28 # obj = Classes.objects.filter(id=2).first() #1 3班 29 # obj.m.add(2) 30 # obj.m.add([4,3]) 31 32 obj = Classes.objects.filter(id=1).first() #1 3班 33 # 刪除 34 # obj.m.remove([4,3]) 35 # 清空 36 obj.m.clear() 37 # 重置 38 obj.m.set([2,3,5]) 39 40 # 查第三張表 41 # 把3班的全部老師列舉 42 obj = Classes.objects.filter(id=1).frist() 43 obj.id 44 obj.titile 45 ret = obj.m.all() # 第三張表 46 # ret是一個 [ 老師1(id,name),obj(id,name) ]
d、其它操做
1 # extra 2 # 3 # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) 4 # Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) 5 # Entry.objects.extra(where=['headline=%s'], params=['Lennon']) 6 # Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) 7 # Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) 8 9 # F 使用查詢條件的值,專門取對象中某列值的操做 10 # 11 # from django.db.models import F 12 # models.Tb1.objects.update(num=F('num')+1) 13 14 15 # Q 與 或 非 的關係構建搜索條件 16 # 17 # 方式一: 18 # Q(nid__gt=10) 19 # Q(nid=8) | Q(nid__gt=10) 20 # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 21 # 方式二: 22 # con = Q() 23 # q1 = Q() 24 # q1.connector = 'OR' 25 # q1.children.append(('id', 1)) 26 # q1.children.append(('id', 10)) 27 # q1.children.append(('id', 9)) 28 # q2 = Q() 29 # q2.connector = 'OR' 30 # q2.children.append(('c1', 1)) 31 # q2.children.append(('c1', 10)) 32 # q2.children.append(('c1', 9)) 33 # con.add(q1, 'AND') 34 # con.add(q2, 'AND') 35 # 36 # models.Tb1.objects.filter(con) 37 38 39 # exists()方法來檢查是否有數據 exists()的檢查能夠避免數據放入queryset的cache。 40 # obj = Book.objects.filter(id=4) 41 # if obj.exists():print("hello world!") 42 43 # 執行原生SQL 44 # 45 # from django.db import connection, connections 46 # cursor = connection.cursor() # cursor = connections['default'].cursor() 47 # cursor.execute("""SELECT * from auth_user where id = %s""", [1]) 48 # row = cursor.fetchone() 49 50 Q、F、exists()
e、補充
# values 取到的是字典集合 # values_list 取到的是沒有鍵的元祖形式 # get 只有在能取到一條數據的時候纔不會報錯(不推薦) # filter([篩選條件]) # all() 倆者取到的都是Query set集合對象 是可迭代、可切片、索引取值 # iterator() ORM的惰性機制 # Publisher.objects.all()或者.filter()等都只是返回了一個QuerySet # 並不會立刻執行sql,而是當調用QuerySet的時候才執行。