內容:css
1.課前複習html
2.django路由規則python
3.django視圖函數mysql
4.django ORMjquery
5.模板git
django預備知識:http://www.javashuo.com/article/p-gaxyavsw-bm.htmlweb
django基礎參考:http://www.cnblogs.com/wupeiqi/articles/5237704.html正則表達式
1、課前複習sql
1.HTTP協議消息格式數據庫
1 請求(request): 2 請求方法 路徑 HTTP/1.1\r\n 3 k1:v1\r\n 4 ...\r\n 5 \r\n 6 請求體 <-- 能夠有,能夠沒有 7 8 響應(response): 9 HTTP/1.1 狀態碼 狀態描述符\r\n 10 k1:v1\r\n 11 Content-Type: text/html; charset=utf8\r\n 12 \r\n 13 響應正文 <-- HTML內容
2.python的web框架本質
3.一個完整的請求過程:
2、django路由系統
在django程序中,能夠經過urls.py文件對全部的url進行任務的分配,根據路由規則的定義選擇不一樣的業務處理函數進行處理,urls.py中規定的對應規則能夠說是路由系統(URLconf)
關於路由規則的詳細內容:http://www.cnblogs.com/liwenzhou/p/8271147.html
1.基本路由規則
基本格式(1.x版本):
1 from django.conf.urls import url 2 3 urlpatterns = [ 4 url(正則表達式, views視圖函數,參數,別名), 5 ]
Django 2.0版本路由系統的寫法:
1 from django.urls import path 2 3 urlpatterns = [ 4 path('articles/', views.articles), 5 path('articles/<int:year>/', views.year_archive), 6 path('articles/<int:year>/<int:month>/', views.month_archive), 7 path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail), 8 ]
2.路由系統正則表達式詳解
基礎樣例 - 分組匹配:
1 from django.conf.urls import url 2 from . import views 3 4 urlpatterns = [ 5 url(r'^articles/2003/$', views.special_case_2003), 6 url(r'^articles/([0-9]{4})/$', views.year_archive), 7 url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), 8 url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), 9 ]
注意:
上面的示例使用簡單的正則表達式分組匹配(經過圓括號)來捕獲URL中的值並以位置參數形式傳遞給視圖;在更高級的用法中,可使用分組命名匹配的正則表達式組來捕獲URL中的值並以關鍵字參數形式傳遞給視圖
在Python的正則表達式中,分組命名正則表達式組的語法是(?P<name>pattern)
,其中name
是組的名稱,pattern
是要匹配的模式
分組命名匹配:
1 from django.conf.urls import url 2 from . import views 3 4 urlpatterns = [ 5 url(r'^articles/2003/$', views.special_case_2003), 6 url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), 7 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), 8 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), 9 ]
這個實現與前面的示例徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數,另外注意不管哪一種方法每一個在路由中捕獲的參數都做爲一個普通的Python字符串傳遞給視圖
另外views.py中能夠給視圖函數的參數設置默認值:
3.django路由分發
1個Django 項目裏面有多個APP目錄你們共有一個 url容易形成混淆,因而路由分發讓每一個APP的擁有了本身單獨的url:
項目目錄下的urls.py:
1 from django.conf.urls import url, include 2 from django.contrib import admin 3 4 urlpatterns = [ 5 # 分發到APP的路由 6 url(r'^basic/', include('basic.urls')), 7 url(r'^app1/', include('app1.urls')), 8 url(r'^app2/', include('app2.urls')), 9 ]
basic這個APP下的urls.py:
1 from django.conf.urls import url 2 from basic import views 3 4 urlpatterns = [ 5 url(r'^index/', views.index), 6 url(r'^login/', views.login), 7 url(r'^register/', views.register), 8 ]
完成上述設置後,basic這個APP的路由只需在本身APP下的urls.py配置便可,訪問時前面帶上basic路徑便可
4.命名URL和URL反向解析
(1)前言
在使用Django 項目時,一個常見的需求是得到URL的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。
人們強烈但願不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 絕不相關的專門的URL 生成機制,由於這樣容易致使必定程度上產生過時的URL。
換句話講,須要的是一個DRY 機制。除了其它有點,它還容許設計的URL 能夠自動更新而不用遍歷項目的源代碼來搜索並替換過時的URL。
獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型(位置參數、關鍵字參數)和值。
Django 提供一個辦法是讓URL 映射是URL 設計惟一的地方。你填充你的URLconf,而後能夠雙向使用它:
(2)命名URL和URL反向解析
前言中第一種方式是咱們在前面的章節中一直討論的用法,是直接得到url的最終形式,能夠稱之爲命名URL
而第二種方式叫作反向解析URL或者簡單的URL 反查
在須要URL 的地方,對於不一樣層級,Django 提供不一樣的工具用於URL 反查:
反向解析URL本質上就是給url匹配模式起別名,而後用過別名拿到具體的URL路徑
用法以下:
1 起別名: 在url匹配模式中,定義name="別名" 2 3 1. 在模板語言裏面使用: 4 {% url "別名" %} --> 獲得具體的URL路徑 5 6 7 2. 在視圖中如何使用: 8 from django.urls import reverse 9 10 reverse("別名") --> 獲得具體的URL路徑 11 12 13 3. 如何傳參數? 14 模板語言中: 15 {% url "別名" 2018 "nb" %} 16 17 視圖函數中 18 傳位置參數: reverse("別名", args=(2018, "nb")) 19 傳關鍵字參數: reverse("別名" kwargs={"year": 2018, "title": "nb"}) 20 21 22 4. namespace 23 爲了防止不一樣的app下面的url匹配模式有重複的別名,能夠給app起別名
(3)實例以下:
urls.py:
1 urlpatterns = [ 2 url(r'^admin/', admin.site.urls, name="admin"), 3 # 分發到APP的路由 4 url(r'^basic/', include('basic.urls', namespace="basic")), 5 ]
1 urlpatterns = [ 2 url(r'^user_list/', views.user_list, name="user_list"), 3 url(r'^add_user/', views.add_user, name="add_user"),
4 ]
views.py:
1 def user_list(request): 2 res = models.UserInfo.objects.all() 3 return render(request, "user/user_list.html", {"user_list": res}) 4 5 def add_user(request): 6 err_msg = "" 7 if request.method == "POST": 8 new_name = request.POST.get("username", None) 9 new_pwd = request.POST.get("password", None) 10 if new_name and new_pwd: 11 models.UserInfo.objects.create(username=new_name, password=new_pwd) 12 return redirect(reverse("basic:user_list")) 13 else: 14 err_msg = "用戶名或密碼不能爲空!" 15 return render(request, "user/add_user.html", {"error": err_msg})
HTML:
1 <a class="btn btn-default" href="{% url "basic:add_user" %}" role="button">添加用戶</a>
3、django視圖系統
視圖系統簡稱視圖,能夠是一個簡單的Python 函數,它接受Web請求而且返回Web響應。響應能夠是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片. . . 是任何東西均可以。不管視圖自己包含什麼邏輯,都要返回響應。
約定將視圖放置在項目或APP目錄中的名爲views.py中(通常爲了模塊化都是放在APP的views裏)
關於視圖系統詳細:http://www.cnblogs.com/liwenzhou/articles/8305104.html
1.最簡單的視圖
不論什麼視圖都包含兩個對象:
最簡單的視圖:
1 from django.shortcuts import HttpResponse 2 3 def easy_view(request): 4 # 每一個視圖函數都使用HttpRequest對象做爲第一個參數,而且一般稱之爲request 5 return HttpResponse("hello world!")
視圖函數,圍繞着兩個對象進行:HttpResponse和HttpRequest
2.HttpRequest
(1)屬性
1 request.path 獲取訪問文件路徑 2 request.path_info 獲取用戶請求的路徑(不包含IP和端口和URL參數) 3 request.method 獲取請求中使用的HTTP方式(POST/GET) 4 request.body 含全部請求體信息 是bytes類型 5 request.GET GET請求的數據(類字典對象) 請求頭中的url中?後面拿值 6 request.POST POST請求的數據(類字典對象) 請求體裏拿值 7 8 request.FILES: 包含全部上傳文件的類字典對象;FILES中的每個Key都是<input type="file" name="" />標籤中 9 name屬性的值,FILES中的每個value同時也是一個標準的python字典對象,包含下面三個Keys: 10 filename: 上傳文件名,用字符串表示 11 content_type: 上傳文件的Content Type 12 content: 上傳文件的原始內容 13 14 request.user: 是一個django.contrib.auth.models.User對象,表明當前登錄的用戶。若是訪問用戶當前 15 沒有登錄,user將被初始化爲django.contrib.auth.models.AnonymousUser的實例。你 16 能夠經過user的is_authenticated()方法來辨別用戶是否登錄: 17 if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware 18 時該屬性纔可用 19 20 request.COOKIES 包含全部cookies的標準Python字典對象;keys和values都是字符串。 21 request.session 惟一可讀寫的屬性,表明當前會話的字典對象;本身有激活Django中的session支持時該屬性纔可用
屬性實例 - 上傳文件:
1 def upload(request): 2 """ 3 保存上傳文件前,數據須要存放在某個位置。默認當上傳文件小於2.5M時,django會將上傳文件的所有內容讀進內存。從內存讀取一次,寫磁盤一次。 4 但當上傳文件很大時,django會把上傳文件寫到臨時文件中,而後存放到系統臨時文件夾中。 5 :param request: 6 :return: 7 """ 8 if request.method == "POST": 9 # 從請求的FILES中獲取上傳文件的文件名,file-name爲頁面上type=files類型input的name屬性值 10 filename = request.FILES["file-name"].name 11 # 在項目目錄下新建一個文件 12 with open(filename, "wb") as f: 13 # 從上傳的文件對象中一點一點讀 14 for chunk in request.FILES["file-name"].chunks(): 15 # 寫入本地文件 16 f.write(chunk) 17 return HttpResponse("上傳OK")
(2)方法
1 request.GET.get('name', None) 拿到GET請求裏name的值(不存在就爲None) 2 request.POST.get('username', None) 拿到GET請求裏username的值(不存在就爲None) 3 若是某個鍵對應有多個值,則不能直接用get取值,須要用getlist,如:request.POST.getlist("hobby")
4
5 獲取請求路徑:
6 請求url: http://127.0.0.1:8000/index.html/23?a=1
7 request.path 結果: /index.html/23
8 request.get_full_path() 結果: /index.html/23?a=1
3.HttpResponse
對於HttpRequest請求對象來講,是由django自動建立的,可是,HttpResponse響應對象就必須咱們本身建立。每一個view請求處理方法必須返回一個響應。HttpResponse類在django.http.HttpResponse
能夠由HttpResponse對象上擴展出多種經常使用方法,以下所示
(1)HttpResponse函數
1 from django.shortcuts import HttpResponse 2 3 4 # 最簡單的視圖函數 5 def easy_view(request): 6 # 返回最簡單的一個響應(一個字符串): hello world! 7 return HttpResponse("hello world!")
補充 - JsonResponse
JsonResponse是HttpResponse的子類,專門用來生成JSON編碼的響應:
1 from django.http import JsonResponse 2 3 response = JsonResponse({'foo': 'bar'}) 4 print(response.content) 5 6 b'{"foo": "bar"}'
默認只能傳遞字典類型,若是要傳遞非字典類型須要設置一下safe關鍵字參數:
response = JsonResponse([1, 2, 3], safe=False)
(2)render函數
做用:將特色頁面渲染後返回給瀏覽器
渲染 -> 給頁面中的參數賦值
render(request, template_name[, context])
結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象
參數以下:
render實例:
1 from django.shortcuts import render 2 3 def my_view(request): 4 # 視圖的代碼寫在這裏 5 return render(request, 'index.html', {'foo': 'bar'})
1 def render(request, template_name, context=None, content_type=None, status=None, using=None): 2 """ 3 Returns a HttpResponse whose content is filled with the result of calling 4 django.template.loader.render_to_string() with the passed arguments. 5 """ 6 content = loader.render_to_string(template_name, context, request, using=using) 7 return HttpResponse(content, content_type, status)
關於render:render方法主要是將從服務器提取的數據,填充到模板中,而後將渲染後的html靜態文件返回給瀏覽器
(3)redirect函數
redirect函數主要用於重定向,默認返回一個臨時的重定向;傳遞permanent=True 能夠返回一個永久的重定向
參數能夠是:
redirect實例:
1 from django.shortcuts import redirect 2 3 # 經過一些對象來重定向(將調用該對象的get_absolute_url方法): 4 def my_view(request): 5 ... 6 object = MyModel.objects.get(...) 7 return redirect(object) 8 9 # 傳遞視圖的名稱和可選參數來重定向(將使用reverse方法進行反向解析出url): 10 def my_view(request): 11 ... 12 return redirect('some-view-name', foo='bar') 13 14 # 傳遞一個url重定向: 15 def my_view(request): 16 ... 17 return redirect('/some/url/')
對比render和redirect:
另外:
臨時重定向(響應狀態碼:302)和永久重定向(響應狀態碼:301)對普通用戶來講是沒什麼區別的,它主要面向的是搜索引擎的機器人。
(4)實戰 - 簡單登陸的完整示例
HTML:
1 form表單日後端提交數據須要注意三點: 2 1. form不是from,全部獲取用戶輸入的標籤都應該放在form裏面, 而且必需要有name屬性 3 2. action屬性控制往哪兒提交,method通常都設置成post 4 3. 提交按鈕必須是type=submit,不能是別的類型
1 <!-- author: wyb --> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <meta charset="UTF-8"> 6 <!-- 移動端適配 --> 7 <meta name="viewport" content="width=device-width, initial-scale=1"> 8 <title>登陸頁面</title> 9 <!-- 引入normalize.css --> 10 <link href="https://cdn.bootcss.com/normalize/8.0.0/normalize.css" rel="stylesheet"> 11 <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> 12 <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" 13 integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> 14 15 <style> 16 body{ 17 background: #eeeeee; 18 } 19 #form-box{ 20 margin-top: 199px; 21 } 22 </style> 23 </head> 24 <body> 25 26 <div class="container-fluid"> 27 <div class="row"> 28 <div class="col-md-4 col-lg-3 col-md-offset-4"> 29 <div id="form-box"> 30 <h3 class="text-center">請登陸</h3> 31 <form class="form-horizontal" method="post" action="/baobao/"> 32 <div class="form-group"> 33 <label for="inputUsername" class="col-sm-3 control-label">用戶名</label> 34 <div class="col-sm-9"> 35 <input name="username" type="text" class="form-control" id="inputUsername" placeholder="輸入用戶名"> 36 </div> 37 </div> 38 <div class="form-group"> 39 <label for="inputPassword3" class="col-sm-3 control-label">密碼</label> 40 <div class="col-sm-9"> 41 <input name="password" type="password" class="form-control" id="inputPassword3" placeholder="輸入密碼"> 42 </div> 43 </div> 44 <div class="form-group"> 45 <div class="col-sm-offset-3 col-sm-9"> 46 <div class="checkbox"> 47 <label> 48 <input type="checkbox"> 記住我 49 </label> 50 </div> 51 </div> 52 </div> 53 <div class="form-group"> 54 <div class="col-sm-offset-3 col-sm-9"> 55 <button type="submit" class="btn btn-primary btn-block">登陸</button> 56 </div> 57 </div> 58 </form> 59 </div> 60 </div> 61 </div> 62 </div> 63 64 65 <!-- 引入jQuery --> 66 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> 67 <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> 68 <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" 69 integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" 70 crossorigin="anonymous"></script> 71 72 </body> 73 </html>
urls:
1 url(r'^login/', views.login),
2 url(r'^baobao/', views.baobao),
views(GET和POST分開寫):
1 def login(request): 2 return render(request, "login.html") 3 4 5 def baobao(request): 6 # 獲取用戶提交的數據 7 # 獲取全部POST的數據: print(request.POST) 8 username = request.POST.get("username", None) 9 password = request.POST.get("password", None) 10 print(username, password) 11 # 作是否登陸成功的判斷 12 if username == "wyb" and password == "wyb666": 13 # 登陸成功 14 return HttpResponse("登陸成功!") 15 return HttpResponse("登陸失敗!")
views(GET和POST一塊兒寫):
1 # 先把form表單的action屬性去掉(不寫就是往當前路由提交) 2 3 # 而後修改login函數以下: 4 def login(request): 5 if request.method == "GET": 6 # 若是是GET請求: 7 return render(request, "login.html") 8 else: 9 # 若是是POST請求: 10 username = request.POST.get("username", None) 11 password = request.POST.get("password", None) 12 print(username, password) 13 # 作是否登陸成功的判斷 14 if username == "wyb" and password == "wyb666": 15 # 登陸成功 16 return HttpResponse("登陸成功!") 17 return HttpResponse("登陸失敗!")
views優化版:
1 # render和redirect實例 2 # 首先在login.html中的form表單結束以前插入一個p標籤(內容: {{ error}}) 3 # 而後修改login函數代碼以下: 4 def login(request): 5 error_msg = "" 6 if request.method == "POST": 7 # 若是是POST請求: 8 username = request.POST.get("username", None) 9 password = request.POST.get("password", None) 10 print(username, password) 11 # 作是否登陸成功的判斷 12 if username == "wyb" and password == "wyb666": 13 # 登陸成功 14 # return HttpResponse("登陸成功!") 15 # 回覆一個特殊的響應(重定向) 這個響應讓用戶的瀏覽器自動請求指定的url 16 return redirect("http://www.luffycity.com") 17 else: 18 # 登陸失敗 19 error_msg = "用戶名或密碼錯誤" 20 # 不是POST走這下面: 21 return render(request, "login.html", {"error": error_msg})
(5)CBV和FBV
以前寫過的都是基於函數的view,就叫FBV。還能夠把view寫成基於類的。
就拿上面寫的登錄爲例:
FBV版:
1 # FBV版登錄 2 def login(request): 3 error_msg = "" 4 if request.method == "POST": 5 username = request.POST.get("username", None) 6 password = request.POST.get("password", None) 7 7 if username == "wyb" and password == "safsfwefvs": 8 return HttpResponse("登陸成功!") 9 else: 10 error_msg = "登錄失敗: 用戶名或密碼錯誤" 11 return render(request, "user/login.html", {"error": error_msg})
CBV版:
1 # CBV版登錄: 2 from django.views import View 3 4 class Login(View): 5 def get(self, request): 6 return render(request, "user/login.html") 7 8 def post(self, request): 9 username = request.POST.get("username", None) 10 password = request.POST.get("password", None) 11 if username == "wyb" and password == "sdfsadf": 12 return HttpResponse("登陸成功!") 13 else: 14 error_msg = "登錄失敗: 用戶名或密碼錯誤" 15 return HttpResponse(error_msg)
注意當使用CBV時,urls.py中也作對應的修改:
# urls.py中 url(r'^login/$', views.Login.as_view()),
4、django ORM
對象關係映射(Object Relational Mapping,簡稱ORM)模式是一種爲了解決面向對象與關係數據庫存在的互不匹配的現象的技術。
簡單的說,ORM是經過使用描述對象和數據庫之間映射的元數據,將程序中的對象自動持久化到關係數據庫中。
ORM在業務邏輯層和數據庫層之間充當了橋樑的做用
ORM詳細內容:http://www.cnblogs.com/liwenzhou/articles/8276526.html
1.ORM介紹
(1)django中的數據庫操做
到目前爲止,當咱們的程序涉及到數據庫相關操做時,咱們通常會這樣作:
django爲使用一種新的方式,即:關係對象映射(Object Relational Mapping,簡稱ORM)來完成上述的數據訪問層
django中遵循 Code Frist 的原則,即:根據代碼中定義的類來自動生成數據庫表
(2)ORM優缺點
優勢:
缺點:
(3)ORM補充說明
ORM對應關係:
1 類 ---> 數據表 2 對象 ---> 數據行 3 屬性 ---> 字段
實例以下:
ORM能作的事:
另外注意ORM不能建立數據庫,須要本身動手建立數據庫
2.django中ORM基礎配置
(1)建立數據庫
create database 數據庫名;
(2)設置數據庫配置
在Django項目中的settings.py中設置鏈接數據庫的相關配置(告訴Django鏈接哪個數據庫)
1 # Database 2 # https://docs.djangoproject.com/en/1.11/ref/settings/#databases 3 4 # 默認使用sqlite數據庫 5 # DATABASES = { 6 # 'default': { 7 # 'ENGINE': 'django.db.backends.sqlite3', 8 # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 9 # } 10 # } 11 12 # 數據庫相關配置: 13 DATABASES = { 14 'default': { 15 'ENGINE': 'django.db.backends.mysql', # 鏈接的數據庫類型 16 'HOST': '127.0.0.1', # 鏈接數據庫的地址 17 'PORT': 3306, # 端口 18 'NAME': "django", # 數據庫名稱 19 'USER': 'root', # 用戶 20 'PASSWORD': 'root' # 密碼 21 } 22 }
(3)__init__.py添加內容
告訴Django用pymysql代替默認的MySQLDB 鏈接MySQL數據庫
在項目/__init__.py文件中,寫下面兩句:
1 import pymysql 2 # 告訴Django用pymysql來代替默認的MySQLdb 3 pymysql.install_as_MySQLdb()
3.django中ORM使用步驟
(1)定義類
在app下面的models.py文件中定義一個類,這個類必須繼承models.Model
1 # ORM相關的只能寫在這個文件裏,寫到別的文件裏django找不到 2 from django.db import models 3 4 5 class UserInfo(models.Model): 6 id = models.AutoField(primary_key=True) # 建立一個自增的主鍵字段 7 # 用戶名及密碼 8 username = models.CharField(null=False, max_length=20) 9 password = models.CharField(null=False, max_length=64)
(2)執行如下命令
4.ORM字段
(1)Django ORM經常使用字段
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 BooleanField(Field) 34 - 布爾值類型 35 36 NullBooleanField(Field): 37 - 能夠爲空的布爾值 38 39 CharField(Field) 40 - 字符類型 41 - 必須提供max_length參數, max_length表示字符長度 42 43 TextField(Field) 44 - 文本類型 45 46 EmailField(CharField): 47 - 字符串類型,Django Admin以及ModelForm中提供驗證機制 48 49 IPAddressField(Field) 50 - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制 51 52 GenericIPAddressField(Field) 53 - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6 54 - 參數: 55 protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6" 56 unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both" 57 58 URLField(CharField) 59 - 字符串類型,Django Admin以及ModelForm中提供驗證 URL 60 61 SlugField(CharField) 62 - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號) 63 64 CommaSeparatedIntegerField(CharField) 65 - 字符串類型,格式必須爲逗號分割的數字 66 67 UUIDField(Field) 68 - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證 69 70 FilePathField(Field) 71 - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能 72 - 參數: 73 path, 文件夾路徑 74 match=None, 正則匹配 75 recursive=False, 遞歸下面的文件夾 76 allow_files=True, 容許文件 77 allow_folders=False, 容許文件夾 78 79 FileField(Field) 80 - 字符串,路徑保存在數據庫,文件上傳到指定目錄 81 - 參數: 82 upload_to = "" 上傳文件的保存路徑 83 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage 84 85 ImageField(FileField) 86 - 字符串,路徑保存在數據庫,文件上傳到指定目錄 87 - 參數: 88 upload_to = "" 上傳文件的保存路徑 89 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage 90 width_field=None, 上傳圖片的高度保存的數據庫字段名(字符串) 91 height_field=None 上傳圖片的寬度保存的數據庫字段名(字符串) 92 93 DateTimeField(DateField) 94 - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 95 96 DateField(DateTimeCheckMixin, Field) 97 - 日期格式 YYYY-MM-DD 98 99 TimeField(DateTimeCheckMixin, Field) 100 - 時間格式 HH:MM[:ss[.uuuuuu]] 101 102 DurationField(Field) 103 - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型 104 105 FloatField(Field) 106 - 浮點型 107 108 DecimalField(Field) 109 - 10進制小數 110 - 參數: 111 max_digits,小數總長度 112 decimal_places,小數位長度 113 114 BinaryField(Field) 115 - 二進制類型 116 117 字段合集
(2) 自定義char字段
1 class FixedCharField(models.Field): 2 """ 3 自定義的char類型的字段類 4 """ 5 def __init__(self, max_length, *args, **kwargs): 6 self.max_length = max_length 7 super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs) 8 9 def db_type(self, connection): 10 """ 11 限定生成數據庫表的字段類型爲char,長度爲max_length指定的值 12 """ 13 return 'char(%s)' % self.max_length
(3)經常使用的字段參數
DateField和DateTimeField纔有的參數:
(4)關係字段
ForeignKey:
外鍵類型在ORM中用來表示外鍵關聯關係,通常把ForeignKey字段設置在 '一對多'中'多'的一方。
字段參數以下:
db_constraint:是否在數據庫中建立外鍵約束,默認爲True,賦值爲False,表示爲軟關聯
1 models.CASCADE: 2 刪除關聯數據,與之關聯也刪除 3 4 models.DO_NOTHING: 5 刪除關聯數據,引起錯誤IntegrityError 6 7 models.PROTECT: 8 刪除關聯數據,引起錯誤ProtectedError 9 10 models.SET_NULL: 11 刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空) 12 13 models.SET_DEFAULT: 14 刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值) 15 16 models.SET: 17 刪除關聯數據, 18 a. 與之關聯的值設置爲指定值,設置:models.SET(值) 19 b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象)
OneToOneField:
一對一字段 一般一對一字段用來擴展已有字段。
字段參數:
示例:
1 # 一對一的關聯關係多用在當一張表的不一樣字段查詢頻次差距過大的狀況下,將本能夠存儲在一張表的字段拆開放置在兩張表中, 2 # 而後將兩張表創建一對一的關聯關係。 3 4 class Author(models.Model): 5 name = models.CharField(max_length=32) 6 info = models.OneToOneField(to='AuthorInfo') 7 8 class AuthorInfo(models.Model): 9 phone = models.CharField(max_length=11) 10 email = models.EmailField()
ManyToManyField:
用於表示多對多的關聯關係。在數據庫中經過第三張表來創建關聯關係。
字段參數:
實例:
1 class Person(models.Model): 2 name = models.CharField(max_length=16) 3 friends = models.ManyToManyField("self") 4 # 此時,person對象就沒有person_set屬性。 5 6 class Person(models.Model): 7 name = models.CharField(max_length=16) 8 friends = models.ManyToManyField("self", symmetrical=False) 9 # 此時,person對象如今就可使用person_set屬性進行反向查詢。
1 # 方式一:自行建立第三張表 2 class Book(models.Model): 3 title = models.CharField(max_length=32, verbose_name="書名") 4 5 class Author(models.Model): 6 name = models.CharField(max_length=32, verbose_name="做者姓名") 7 8 9 # 本身建立第三張表,分別經過外鍵關聯書和做者 10 class Author2Book(models.Model): 11 author = models.ForeignKey(to="Author") 12 book = models.ForeignKey(to="Book") 13 14 class Meta: 15 unique_together = ("author", "book") 16 17 18 # 方式二:經過ManyToManyField自動建立第三張表 19 class Book(models.Model): 20 title = models.CharField(max_length=32, verbose_name="書名") 21 22 # 經過ORM自帶的ManyToManyField自動建立第三張表 23 class Author(models.Model): 24 name = models.CharField(max_length=32, verbose_name="做者姓名") 25 books = models.ManyToManyField(to="Book", related_name="authors") 26 27 28 # 方式三:設置ManyTomanyField並指定自行建立的第三張表 29 class Book(models.Model): 30 title = models.CharField(max_length=32, verbose_name="書名") 31 32 # 本身建立第三張表,並經過ManyToManyField指定關聯 33 class Author(models.Model): 34 name = models.CharField(max_length=32, verbose_name="做者姓名") 35 books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book")) 36 # through_fields接受一個2元組('field1','field2'): 37 # 其中field1是定義ManyToManyField的模型外鍵的名(author),field2是關聯目標模型(book)的外鍵名。 38 39 class Author2Book(models.Model): 40 author = models.ForeignKey(to="Author") 41 book = models.ForeignKey(to="Book") 42 43 class Meta: 44 unique_together = ("author", "book") 45 46 # 注意: 當咱們須要在第三張關係表中存儲額外的字段時,就要使用第三種方式 47 可是當咱們使用第三種方式建立多對多關聯關係時,就沒法使用set、add、remove、clear方法來管理多對多的關係了, 48 須要經過第三張表的model來管理多對多關係
(5)元信息
ORM對應的類裏面包含另外一個Meta類,而Meta類封裝了一些數據庫的信息。主要字段以下:
例如設置重寫表名:
1 class Meta: 2 db_table = "xxx"
5.ORM操做
(1)操做數據表 --> 建立表/刪除表/修改表
使用ORM操做數據表實際上就是按上述ORM使用步驟來操做models.py裏面的類(把上面第一步替換成以下步驟):
(2)操做數據行 --> 數據的增刪改查
ORM操做數據詳細講解看這裏:http://www.javashuo.com/article/p-emhmbenx-bp.html
詳細以下:
1 # 增: 2 # 3 # models.Tb.objects.create(c1='xx', c2='oo') 增長一條數據,能夠接受字典類型數據 **kwargs 4 # obj = models.Tb(c1='xx', c2='oo') 5 # obj.save() 6 7 8 # 查 9 # 10 # models.Tb.objects.all() # 獲取所有 11 # models.Tb.objects.filter(name='seven') # 獲取指定條件的數據 12 13 # 刪 14 # 15 # models.Tb1.objects.filter(name='seven').delete() # 刪除指定條件的數據 16 17 # 改 18 # models.Tb1.objects.filter(name='seven').update(gender='0') # 將指定條件的數據更新,均支持 **kwargs 19 # obj = models.Tb1.objects.get(id=1) 20 # obj.c1 = '111' 21 # obj.save() # 修改單條數據 22 23 24
6.ORM表關係
(1)三種表關係
ORM表關係有以下三種:
實例以下:
一對多:當一張表中建立一行數據時,有一個單選的下拉框(能夠被重複選擇)
例如:建立用戶信息時候,須要選擇一個用戶類型【普通用戶】【會員用戶】【超級會員用戶】等
多對多:在某表中建立一行數據是,有一個能夠多選的下拉框
例如:建立用戶信息,須要爲用戶指定多個愛好 但同時一個愛好能夠被多個用戶選擇
一對一: 好比公司對應的董事長只能有一個
(2)詳細使用
1 ForeignKey(ForeignObject) # ForeignObject(RelatedField) 2 to, # 要進行關聯的表名 3 to_field=None, # 要關聯的表中的字段名稱 4 on_delete=None, # 當刪除關聯表中的數據時,當前表與其關聯的行的行爲 5 - models.CASCADE,刪除關聯數據,與之關聯也刪除 6 - models.DO_NOTHING,刪除關聯數據,引起錯誤IntegrityError 7 - models.PROTECT,刪除關聯數據,引起錯誤ProtectedError 8 - models.SET_NULL,刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空) 9 - models.SET_DEFAULT,刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值) 10 - models.SET,刪除關聯數據, 11 a. 與之關聯的值設置爲指定值,設置:models.SET(值) 12 b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象) 13 14 def func(): 15 return 10 16 17 class MyModel(models.Model): 18 user = models.ForeignKey( 19 to="User", 20 to_field="id" 21 on_delete=models.SET(func),) 22 related_name=None, # 反向操做時,使用的字段名,用於代替 【表名_set】 如: obj.表名_set.all() 23 related_query_name=None, # 反向操做時,使用的鏈接前綴,用於替換【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') 24 limit_choices_to=None, # 在Admin或ModelForm中顯示關聯數據時,提供的條件: 25 # 如: 26 - limit_choices_to={'nid__gt': 5} 27 - limit_choices_to=lambda : {'nid__gt': 5} 28 29 from django.db.models import Q 30 - limit_choices_to=Q(nid__gt=10) 31 - limit_choices_to=Q(nid=8) | Q(nid__gt=10) 32 - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 33 db_constraint=True # 是否在數據庫中建立外鍵約束 34 parent_link=False # 在Admin中是否顯示關聯數據 35 36 37 OneToOneField(ForeignKey) 38 to, # 要進行關聯的表名 39 to_field=None # 要關聯的表中的字段名稱 40 on_delete=None, # 當刪除關聯表中的數據時,當前表與其關聯的行的行爲 41 42 ###### 對於一對一 ###### 43 # 1. 一對一其實就是 一對多 + 惟一索引 44 # 2.當兩個類之間有繼承關係時,默認會建立一個一對一字段 45 # 以下會在A表中額外增長一個c_ptr_id列且惟一: 46 class C(models.Model): 47 nid = models.AutoField(primary_key=True) 48 part = models.CharField(max_length=12) 49 50 class A(C): 51 id = models.AutoField(primary_key=True) 52 code = models.CharField(max_length=1) 53 54 ManyToManyField(RelatedField) 55 to, # 要進行關聯的表名 56 related_name=None, # 反向操做時,使用的字段名,用於代替 【表名_set】 如: obj.表名_set.all() 57 related_query_name=None, # 反向操做時,使用的鏈接前綴,用於替換【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') 58 limit_choices_to=None, # 在Admin或ModelForm中顯示關聯數據時,提供的條件: 59 # 如: 60 - limit_choices_to={'nid__gt': 5} 61 - limit_choices_to=lambda : {'nid__gt': 5} 62 63 from django.db.models import Q 64 - limit_choices_to=Q(nid__gt=10) 65 - limit_choices_to=Q(nid=8) | Q(nid__gt=10) 66 - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 67 symmetrical=None, # 僅用於多對多自關聯時,symmetrical用於指定內部是否建立反向操做的字段 68 # 作以下操做時,不一樣的symmetrical會有不一樣的可選字段 69 models.BB.objects.filter(...) 70 71 # 可選字段有:code, id, m1 72 class BB(models.Model): 73 74 code = models.CharField(max_length=12) 75 m1 = models.ManyToManyField('self',symmetrical=True) 76 77 # 可選字段有: bb, code, id, m1 78 class BB(models.Model): 79 80 code = models.CharField(max_length=12) 81 m1 = models.ManyToManyField('self',symmetrical=False) 82 83 through=None, # 自定義第三張表時,使用字段用於指定關係表 84 through_fields=None, # 自定義第三張表時,使用字段用於指定關係表中那些字段作多對多關係表 85 from django.db import models 86 87 class Person(models.Model): 88 name = models.CharField(max_length=50) 89 90 class Group(models.Model): 91 name = models.CharField(max_length=128) 92 members = models.ManyToManyField( 93 Person, 94 through='Membership', 95 through_fields=('group', 'person'), 96 ) 97 98 class Membership(models.Model): 99 group = models.ForeignKey(Group, on_delete=models.CASCADE) 100 person = models.ForeignKey(Person, on_delete=models.CASCADE) 101 inviter = models.ForeignKey( 102 Person, 103 on_delete=models.CASCADE, 104 related_name="membership_invites", 105 ) 106 invite_reason = models.CharField(max_length=64) 107 db_constraint=True, # 是否在數據庫中建立外鍵約束 108 db_table=None, # 默認建立第三張表時,數據庫中表的名稱
(3)ORM多對多關聯查詢原理
多對多其實本質上要經過一張中間表來實現查找,中間表就以下圖中的author2book表:
(4)使用實例 - 圖書管理系統
表結構說明:
1 圖書管理系統: 2 主要是練習增刪改查操做以及表與表之間的關聯關係 3 4 圖書管理系統的三種角色: 出版社、書、做者,這三種關係對應三張表 5 6 表之間的關係 7 一本書 只能 有一個出版社 8 一本書 能有 多個做者 9 一個做者 能寫 多本書 10 11 出版社和書: 一對多 --> 外鍵(放在多的一端) 12 書和做者: 多對多 --> 用第三張表作關聯
ORM類以下:
1 from django.db import models 2 3 # 出版社 4 class Publisher(models.Model): 5 id = models.AutoField(primary_key=True) 6 # 建立一個惟一的不爲空的字段 7 name = models.CharField(max_length=64, null=False, unique=True) 8 9 def __str__(self): 10 return "<Publisher Object: {}>".format(self.name) 11 12 13 # 書 14 class Book(models.Model): 15 id = models.AutoField(primary_key=True) 16 # 建立一個惟一的不爲空的字段 17 title = models.CharField(max_length=64, null=False, unique=True) 18 # 和出版社關聯的外鍵字段 存儲到數據中會自動加上_id變成publisher_id 19 publisher = models.ForeignKey(to="Publisher") 20 21 def __str__(self): 22 return "<Book Object: {}>".format(self.title) 23 24 25 # 做者 26 class Author(models.Model): 27 id = models.AutoField(primary_key=True) 28 name = models.CharField(max_length=32, null=False, unique=True) 29 book = models.ManyToManyField(to="Book") # 告訴ORM Author和Book是多對多關係 自動生成第三張表 30 31 def __str__(self): 32 return "<Author Object: {}>".format(self.name)
添加書籍:
1 def add_book(request): 2 if request.method == "POST": 3 new_title = request.POST.get("book_title") 4 new_publisher_id = request.POST.get("publisher") # 書籍關聯的出版社id 5 # print(new_title, new_publisher_id) 6 if new_title: 7 models.Book.objects.create(title=new_title, publisher_id=new_publisher_id) 8 9 return redirect("/book/book_list/")
添加做者:
1 def add_author(request): 2 if request.method == "POST": 3 # 注意post提交若是獲取多選要用getlist: 4 author_name = request.POST.get("author_name") 5 books = request.POST.getlist("books") # book的一系列id 6 # print(author_name, books) 7 # 建立做者並把做者和書籍創建關係 8 if author_name: 9 new_author_obj = models.Author.objects.create(name=author_name) 10 new_author_obj.book.set(books) 11 12 return redirect("/book/author_list/")
編輯書籍:
1 def edit_book(request): 2 if request.method == "POST": 3 # 從提交的數據裏面取要編輯的書的如下內容: id 書名 書關聯的出版社 4 edit_id = request.POST.get("id") 5 new_title = request.POST.get("book_title") 6 new_publisher_id = request.POST.get("publisher") 7 # 書名爲空或書關聯的出版社不存在時重定向 8 if not new_title or not models.Publisher.objects.filter(id=new_publisher_id): 9 return redirect("/book/book_list/") 10 # 更新 11 edit_book_obj = models.Book.objects.filter(id=edit_id)[0] 12 if edit_book_obj: 13 edit_book_obj.title = new_title # 更新書名 14 edit_book_obj.publisher_id = new_publisher_id # 更新書籍關聯的出版社 15 # 將修改提交到數據庫 16 edit_book_obj.save() 17 else: 18 return HttpResponse("書籍不存在!") 19 # 返回書籍列表頁面,查看是否編輯成功 20 return redirect("/book/book_list/")
編輯做者:
1 def edit_author(request): 2 if request.method == "POST": 3 # 從提交的數據裏面取要編輯的做者的如下內容: id 做者名 做者的一系列做品id 4 edit_author_id = request.POST.get("author_id") 5 new_author_name = request.POST.get("author_name") 6 new_books = request.POST.getlist("books") 7 print(edit_author_id, new_author_name, new_books) 8 # 做者名爲空時重定向 9 if not new_author_name: 10 return redirect("/book/author_list/") 11 # 更新 12 edit_author_obj = models.Author.objects.filter(id=edit_author_id)[0] 13 if edit_author_obj: 14 edit_author_obj.name = new_author_name # 更新做者名 15 edit_author_obj.book.set(new_books) # 更新做者關聯的做品 16 # 將修改提交到數據庫 17 edit_author_obj.save() 18 else: 19 return HttpResponse("做者不存在!") 20 # 返回書籍列表頁面,查看是否編輯成功 21 return redirect("/book/author_list/")
注意:以上添加功能和編輯功能沒有get請求,實際上在這裏後端省去了對get請求的處理(也就是添加和編輯沒有新頁面出現),
在這裏點擊添加或編輯後會在當前頁面(書籍列表頁或做者列表頁)出現一個彈框,點擊彈框的提交鍵便可向後端提交數據,
關於彈框的實現,能夠自定義彈框,也可使用Bootstrap的彈框樣式,我我的是直接使用Bootstrap的彈框
7.其餘
數據已有數據修改表結構問題:
5、模板
模板詳細內容:http://www.cnblogs.com/liwenzhou/p/7931828.html
1.經常使用語法
只須要記兩種特殊符號:{{ }}和 {% %}
變量相關的用{{}},邏輯相關的用{%%}
(1)變量相關
1 {{ 變量名 }} -> 變量名由字母數字和下劃線組成 2 點(.)在模板語言中有特殊的含義,用來獲取對象的相應屬性值 3 4 {# 這是註釋 #} 5 6 {# 取s中的第一個參數 #} 7 {{ s.0 }} 8 {# 取字典中key的值 #} 9 {{ d.name }} 10 {# 取對象的name屬性 #} 11 {{ person_list.0.name }} 12 {# .操做只能調用不帶參數的方法 #} 13 {{ person_list.0.dream }}
(2)tags
1 # for相關 2 for循環: 3 <ul> 4 {% for user in user_list %} 5 <li>{{ user.name }}</li> 6 {% endfor %} 7 </ul> 8 9 for循環中可用的參數: 10 forloop.counter 當前循環的索引值(從1開始) 11 forloop.counter0 當前循環的索引值(從0開始) 12 forloop.revcounter 當前循環的倒序索引值(從1開始) 13 forloop.revcounter0 當前循環的倒序索引值(從0開始) 14 forloop.first 當前循環是否是第一次循環(布爾值) 15 forloop.last 當前循環是否是最後一次循環(布爾值) 16 forloop.parentloop 本層循環的外層循環 17 18 for ... empty: 19 <ul> 20 {% for user in user_list %} 21 <li>{{ user.name }}</li> 22 {% empty %} 23 <li>空空如也</li> 24 {% endfor %} 25 </ul> 26 27 28 # if相關 29 if和else: 30 {% if 判斷條件 %} 31 xxx 32 {% else %} 33 xxx 34 {% endif %} 35 36 37 if,elif和else: 38 {% if 判斷條件 %} 39 xxx 40 {% elif 判斷條件 %} 41 xxx 42 {% else %} 43 xxx 44 {% endif %} 45 46 另外if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷 47 if ... in 判斷: 48 {% if xxx in xxx %} 49 ... 50 {% endif %} 51 52 53 with: 定義一箇中間變量 54 {% with total=business.employees.count %} 55 {{ total }} employee{{ total|pluralize }} 56 {% endwith %}
(3)filter
filter主要是針對模板中的變量作一些額外的操做,語法: {{ value|filter_name:參數 }}
常見的以下:
safe - 關閉自動轉義
Django的模板中會對HTML標籤和JS等語法標籤進行自動轉義,緣由顯而易見,這樣是爲了安全(防止XSS攻擊)。可是有的時候咱們可能不但願這些HTML元素被轉義,好比咱們作一個內容管理系統,後臺添加的文章中是通過修飾的,這些修飾多是經過一個相似於FCKeditor編輯加註了HTML修飾符的文本,若是自動轉義的話顯示的就是保護HTML標籤的源文件。爲了在Django中關閉HTML的自動轉義有兩種方式,若是是一個單獨的變量咱們能夠經過過濾器「|safe」的方式告訴Django這段代碼是安全的沒必要轉義。
好比:
value = "<a href='#'>點我</a>"
1 {{ value|safe}}
自定義filter
自定義過濾器只是帶有一個或兩個參數的Python函數:
例如,在過濾器{{var|foo:「bar」}}中,過濾器foo將傳遞變量var和參數「bar」。
自定義filter代碼文件(py文件)要放在以下位置:
1 app/ 2 __init__.py 3 models.py 4 templatetags/ # 在app下面新建一個package package 5 __init__.py 6 app_filters.py # 建一個存放自定義filter的文件 7 views.py
編寫自定義filter:
1 from django import template 2 register = template.Library() 3 4 # 帶參數的filter 5 @register.filter(name="cut") 6 def cut(value, arg): 7 return value.replace(arg, "") 8 9 # 不帶參數的filter 10 @register.filter(name="addSB") 11 def add_sb(value): 12 return "{} SB".format(value)
上述代碼註釋中的參數是指filter中的參數,而真正函數中的第一個參數(函數參數)永遠傳入的是value的值(|前面那個值)
使用自定義filter:
1 {# 先導入咱們自定義filter那個文件 #} 2 {% load app_filters %} 3 4 {# 使用咱們自定義的filter #} 5 {{ somevariable|cut:"0" }} 6 {{ d.name|addSB }}
2.母版和繼承
(1)爲何要有母版和繼承
把多個頁面公用的部分提取出來,放在一個 母版 裏面。其餘的頁面只須要 繼承 母版就能夠了。能夠簡化代碼,寫更少的代碼
(2)具體使用步驟
base.html:
1 <!-- 頁面主體 --> 2 <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> 3 {% block page-main %} 4 5 {% endblock %} 6 </div>
具體的頁面中:
1 {# 繼承母版 #} 2 {% extends "base.html" %} 3 4 {# 把本身頁面的內容塞到母版中相應的位置 #} 5 6 {% block page-main %} 7 <h1>這是具體頁面</h1> 8 {% endblock %}
(3)使用的注意事項
3.組件及靜態文件
(1)什麼是模板中的組件
能夠將經常使用的頁面內容如導航條,頁尾信息等組件保存在單獨的文件中,而後在須要使用的地方按以下語法導入便可:
1 {% include 'navbar.html' %}
(2)靜態文件導入問題
靜態文件:圖片、CSS、js
前面咱們的靜態文件的路徑都是寫死的,如過將static文件夾的名字改成static333,在代碼中咱們還要修改多處,這樣十分不方便,不過django中提供了方法,可讓HTML中的靜態文件路徑動態跟隨文件夾的名字變化而變化,從而實現動態導入
引入CSS:
1 {% load static %} 2 <link href="{% static 'CSS路徑' %}" rel="stylesheet">
引入圖片:
1 {% load static %} 2 <img src="{% static '圖片路徑' %}" alt="Hi" />
引用JS文件:
1 {% load static %} 2 <script src="{% static 'js路徑' %}"></script>
上述導入實例:
另外某個文件多處被用到能夠存爲一個變量:
1 {% load static %} 2 {% static "images/hi.jpg" as myphoto %} 3 <img src="{{ myphoto }}"></img>
(3)get_static_prefix
上面的導入靜態文件過程,是自動拼接static目錄名和後面的路徑,導入咱們也能夠手動拼接:
1 {% load static %} 2 <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" /> 3 4 或者: 5 {% load static %} 6 {% get_static_prefix as STATIC_PREFIX %} 7 8 <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" /> 9 <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />
(4)自定義simpletag
相似上面的自定義filter不過使用起來更加自由
自定義simpletag文件(py文件)放在以下位置:
1 app/ 2 __init__.py 3 models.py 4 templatetags/ # 在app下面新建一個package -> 放自定義filter文件和自定義simpletag文件 5 __init__.py 6 app_filters.py # 建一個存放自定義filter的文件 7 app_simpletag.py # 建一個存放自定義simpletag的文件 8 views.py
編寫自定義simpletag:
1 from django import template 2 3 register = template.Library() 4 5 @register.simple_tag(name="plus") 6 def plus(a, b, c): 7 return "{} + {} + {}".format(a, b, c)
使用自定義simpletag:
1 {% load app_simpletag.py %} 2 3 {# simple tag #} 4 {% plus "1" "2" "abc" %}
(5)inclusion_tag
上面的自定義simpletag沒法返回HTML,要返回HTML就要使用inclusion_tag,使用方法以下:
1 templatetags/my_inclusion.py: 2 from django import template 3 register = template.Library() 4 5 @register.inclusion_tag('result.html') 6 def show_results(n): 7 n = 1 if n < 1 else int(n) 8 data = ["第{}項".format(i) for i in range(1, n+1)] 9 return {"data": data} 10 11 12 templates/result.html:13 <ul> 14 {% for choice in data %} 15 <li>{{ choice }}</li> 16 {% endfor %} 17 </ul> 18 19 20 templates/index.html: 21 <!DOCTYPE html> 22 <html lang="en"> 23 <head> 24 <meta charset="UTF-8"> 25 <meta http-equiv="x-ua-compatible" content="IE=edge"> 26 <meta name="viewport" content="width=device-width, initial-scale=1"> 27 <title>inclusion_tag test</title> 28 </head> 29 <body> 30 31 {% load inclusion_tag_test %} 32 {% show_results 10 %} 33 34 </body> 35 </html>