Django 1 流程: (1) 設計url: url(r'^timer/', timer), # timer(request) (2) 構建視圖函數: 在views.py: def timer(request): import time ctime=time.time() return render(request,"timer.html",{"ctime":ctime}) (3) templates:timer.html <p>當前時間:{{ ctime }}</p> 2 URL控制器(路由層): 簡單配置 分組 有名分組 分發 反向解析 3 MTV--View(視圖層): 請求對象 request: request.GET request.POST request.method request.path 響應對象: Httpresponse() render() redirect() 4 MTV--Template(模板層) 渲染變量 {{ }} 深度查詢句點符 過濾器{{ var|filter:參數}} add date safe filesizeformat 渲染標籤 {% %} for if url 反向解析 csrftoken 自定義過濾器和標籤 4 MTV--Model(模型層) ORM---對象關係映射 class Book(model.Model): title=models.CharFiled(max_length=32) create table book ( title varchar(32) ) 類名 ------表名 類屬性 ------表字段 類實例對象 ------表記錄 單表記錄操做: Book id title 1 python 2 java 添加記錄: # 方式1: # obj新添加記錄對象 obj=Book.objects.create(title="python") # 方式2: obj=Book(title="java") obj.save() 查詢記錄API(QuerySet): <1> all(): 查詢全部結果 <2> filter(**kwargs): 它包含了與所給篩選條件相匹配的對象 <3> get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個, 若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 <5> exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象 <4> values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列 model的實例化對象,而是一個可迭代的字典序列 <9> values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 <6> order_by(*field): 對查詢結果排序 <7> reverse(): 對查詢結果反向排序 <8> distinct(): 從返回結果中剔除重複紀錄 <10> count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。 <11> first(): 返回第一條記錄 <12> last(): 返回最後一條記錄 <13> exists(): 若是QuerySet包含數據,就返回True,不然返回False 模糊查詢: __ 刪除記錄 Book.objects.filter(price=123,title="python").delete() 更新記錄: Book.objects.filter(price=123,title="python").update(title="python123") mysql表關係 一對多關係:關聯字段 多對多關係:建立關係表 Book title=... publish=Foreignkey(to="Publish",to_field="") authors= Publish name=.... Author name=.... Book2Author
Django的MTV分別表明:css
Model(模型):和數據庫相關的,負責業務對象與數據庫的對象(ORM)html
Template(模板):放全部的html文件,負責如何把頁面展現給用戶前端
模板語法:目的是將白變量(數據庫的內容)如何巧妙的嵌入到html頁面中java
View(視圖):負責業務邏輯,並在適當的時候調用Model和Templatepython
此外,Django還有一個URL分發器。它的做用是將一個個URL的頁面請求分別發給不一樣的Views處理,Views再調用相應的Model和Template。mysql
pip3 install django
建立一個Django項目分兩種方式建立:jquery
文件——新建項目——切到Djangonginx
建立成功後會自動生成這樣一個工程。目錄結構以下:git
django-admin.py startproject 項目名稱
django-admin startproject mysite
建立成功後會生成這樣一個工程。目錄結構以下:web
python3 manage.py startapp blog(應用名稱)
建立成功後會生成這樣一個工程。目錄結構以下:
python3 manage.py runserver 8080
這樣咱們的django就啓動起來了!當咱們訪問:http://127.0.0.1:8080/時就能夠看到:
''' python3 manage.py syncdb 注意:Django 1.7.1 及以上的版本須要用如下命令 python3 manage.py makemigrations python3 manage.py migrate '''
這種方法能夠建立表,當你在models.py中新增了類時,運行它就能夠自動在數據庫中建立表了,不用手動建立。
python3 manage.py flush
此命令會詢問是 yes 仍是 no, 選擇 yes 會把數據所有清空掉,只留下空表。
''' python3 manage.py createsuperuser # 按照提示輸入用戶名和對應的密碼就行了郵箱能夠留空,用戶名和密碼必填 # 修改 用戶密碼能夠用: python3 manage.py changepassword username '''
python3 manage.py shell
這個命令和 直接運行 python 進入 shell 的區別是:你能夠在這個 shell 裏面調用當前項目的 models.py 中的 API,對於操做數據的測試很是方便。
python3 manage.py dbshell
Django 會自動進入在settings.py中設置的數據庫,若是是 MySQL 或 postgreSQL,會要求輸入數據庫用戶密碼。
在這個終端能夠執行數據庫的SQL語句。若是您對SQL比較熟悉,可能喜歡這種方式。
python3 manage.py #########切換到項目目錄下
查看全部的命令,忘記子名稱的時候特別有用。
概述: 靜態文件交由Web服務器處理,Django自己不處理靜態文件。簡單的處理邏輯以下(以nginx爲例): URI請求-----> 按照Web服務器裏面的配置規則先處理,以nginx爲例,主要求配置在nginx. conf裏的location |---------->若是是靜態文件,則由nginx直接處理 |---------->若是不是則交由Django處理,Django根據urls.py裏面的規則進行匹配 以上是部署到Web服務器後的處理方式,爲了便於開發,Django提供了在開發環境的對靜態文件的處理機制,方法是這樣:
static配置:
STATIC主要指的是如css,js,images這樣文件:
STATIC_URL = '/static/' # 別名 STATICFILES_DIRS = ( os.path.join(BASE_DIR,"static"), #實際名 ,即實際文件夾的名字 ) ''' 注意點1: django對引用名和實際名進行映射,引用時,只能按照引用名來,不能按實際名去找 <script src="/statics/jquery-3.1.1.js"></script> ------error-----不能直接用,必須用STATIC_URL = '/static/': <script src="/static/jquery-3.1.1.js"></script> 注意點2: STATICFILES_DIRS = ( ("app01",os.path.join(BASE_DIR, "app01/statics")), ) <script src="/static/app01/jquery.js"></script> '''
have a try:
http://127.0.0.1:8000/static/jquery.js
media配置:
# in settings: MEDIA_URL="/media/" MEDIA_ROOT=os.path.join(BASE_DIR,"app01","media","upload") # in urls: from django.views.static import serve url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
have a try:
http://127.0.0.1:8000/media/1.png
''' 靜態文件的處理又包括STATIC和MEDIA兩類,這每每容易混淆,在Django裏面是這樣定義的: MEDIA:指用戶上傳的文件,好比在Model裏面的FileFIeld,ImageField上傳的文件。若是你定義 MEDIA_ROOT=c:\temp\media,那麼File=models.FileField(upload_to="abc/")#,上傳的文件就會被保存到c:\temp\media\abc eg: class blog(models.Model): Title=models.charField(max_length=64) Photo=models.ImageField(upload_to="photo") 上傳的圖片就上傳到c:\temp\media\photo,而在模板中要顯示該文件,則在這樣寫 在settings裏面設置的MEDIA_ROOT必須是本地路徑的絕對路徑,通常是這樣寫: BASE_DIR= os.path.abspath(os.path.dirname(__file__)) MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\\','/') MEDIA_URL是指從瀏覽器訪問時的地址前綴,舉個例子: MEDIA_ROOT=c:\temp\media\photo MEDIA_URL="/data/" 在開發階段,media的處理由django處理: 訪問http://localhost/data/abc/a.png就是訪問c:\temp\media\photo\abc\a.png 在模板裏面這樣寫<img src="/media/abc/a.png"> 在部署階段最大的不一樣在於你必須讓web服務器來處理media文件,所以你必須在web服務器中配置, 以便能讓web服務器能訪問media文件 以nginx爲例,能夠在nginx.conf裏面這樣: location ~/media/{ root/temp/ break; } 具體能夠參考如何在nginx部署django的資料。 '''
URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要爲該URL調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。
''' urlpatterns = [ url(正則表達式, views視圖函數,參數,別名), ] 參數說明: 一個正則表達式字符串 一個可調用對象,一般爲一個視圖函數或一個指定視圖函數路徑的字符串 可選的要傳遞給視圖函數的默認參數(字典形式) 一個可選的name參數
'''
######項目cms中的urls.py中的內容 from django.conf.urls import url from . 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})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
#############說明 ''' NOTE: 1 一旦匹配成功則再也不繼續 2 若要從URL 中捕獲一個值,只須要在它周圍放置一對圓括號。 3 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles。 4 每一個正則表達式前面的'r' 是可選的可是建議加上。 一些請求的例子: /articles/2005/3/ 不匹配任何URL 模式,由於列表中的第三個模式要求月份應該是兩個數字。 /articles/2003/ 將匹配列表中的第一個模式不是第二個,由於模式按順序匹配,第一個會首先測試是否匹配。 /articles/2005/03/ 請求將匹配列表中的第三個模式。Django 將調用函數 views.month_archive(request, '2005', '03')。 '''
#設置項是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑 APPEND_SLASH=True
上面的示例使用簡單的、沒有命名的正則表達式組(經過圓括號)來捕獲URL 中的值並以位置 參數傳遞給視圖。在更高級的用法中,可使用命名的正則表達式組來捕獲URL 中的值並以關鍵字 參數傳遞給視圖。
在Python 正則表達式中,命名正則表達式組的語法是(?P<name>pattern),其中name 是組的名稱,pattern 是要匹配的模式。
下面是以上URLconf 使用命名組的重寫:
from app02 import views from django.conf.urls import url urlpatterns = [ #無名分組 url(r'^article/\d{4}', views.year) , url(r'^article/(\d{4})$', views.year2), 若是有多個匹配同樣的時候,誰放在上面就匹配誰,上面的就會把下面的覆蓋了 正則加上括號,就是分組,會把分組的內容做爲year2函數的參數傳進去 url(r'^article/(\d{4})/(\d{2})$', views.year_month), # 有名分組(就是給分組起個名字,這樣定義的好處就是按照關鍵字參數去傳參了,指名道姓的方式) url(r'^article/(?P<year>\d{4})/(?P<month>\d{2})$', views.year_month_hasname) ]
這個實現與前面的示例徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數。例如:
/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 會更加明晰且不容易產生參數順序問題的錯誤 —— 你能夠在你的視圖函數定義中從新安排參數的順序。固然,這些好處是以簡潔爲代價;有些開發人員認爲命名組語法醜陋而繁瑣。
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等等 —— 都將路由到相同的函數。
每一個捕獲的參數都做爲一個普通的Python 字符串傳遞給視圖,不管正則表達式使用的是什麼匹配方式。例如,下面這行URLconf 中:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
views.year_archive() 的year 參數將是一個字符串
有一個方便的小技巧是指定視圖參數的默認值。 下面是一個URLconf 和視圖的示例:
# 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 值。
#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')), ]
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 框架中使用,來傳遞元數據和選項給視圖。
在使用Django 項目時,一個常見的需求是得到URL 的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。
人們強烈但願不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 絕不相關的專門的URL 生成機制,由於這樣容易致使必定程度上產生過時的URL。
換句話講,須要的是一個DRY 機制。除了其它有點,它還容許設計的URL 能夠自動更新而不用遍歷項目的源代碼來搜索並替換過時的URL。
獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型(位置參數、關鍵字參數)和值。
Django 提供一個辦法是讓URL 映射是URL 設計惟一的地方。你填充你的URLconf,而後能夠雙向使用它:
l 根據用戶/瀏覽器發起的URL 請求,它調用正確的Django 視圖,並從URL 中提取它的參數須要的值。
l 根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的URL。
第一種方式是咱們在前面的章節中一直討論的用法。第二種方式叫作反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查。
在須要URL 的地方,對於不一樣層級,Django 提供不一樣的工具用於URL 反查:
l 在模板中:使用url 模板標籤。
l 在Python 代碼中:使用django.core.urlresolvers.reverse() 函數。
l 在更高層的與處理Django 模型實例相關的代碼中:使用get_absolute_url() 方法。
例子:
考慮下面的URLconf:
from django.conf.urls import url from . import views urlpatterns = [ #... url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'), #... ]
根據這裏的設計,某一年nnnn對應的歸檔的URL是/articles/nnnn/。
你能夠在模板的代碼中使用下面的方法得到它們:
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a> <ul> {% for yearvar in year_list %} <li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li> {% endfor %} </ul>
在Python 代碼中,這樣使用:
from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect def redirect_to_year(request): # ... year = 2006 # ... return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
若是出於某種緣由決定按年歸檔文章發佈的URL應該調整一下,那麼你將只須要修改URLconf 中的內容。
在某些場景中,一個視圖是通用的,因此在URL 和視圖之間存在多對一的關係。對於這些狀況,當反查URL 時,只有視圖的名字還不夠。
命名空間(英語:Namespace)是表示標識符的可見範圍。一個標識符可在多個命名空間中定義,它在不一樣命名空間中的含義是互不相干的。這樣,在一個新的命名空間中可定義任何標識符,它們不會與任何已有的標識符發生衝突,由於已有的定義都處於其它命名空間中。
因爲name沒有做用域,Django在反解URL時,會在項目全局順序搜索,當查找到第一個name指定URL時,當即返回
咱們在開發項目時,會常用name屬性反解出URL,當不當心在不一樣的app的urls中定義相同的name時,可能會致使URL反解錯誤,爲了不這種事情發生,引入了命名空間。
project.urls:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^app01/', include("app01.urls",namespace="app01")), url(r'^app02/', include("app02.urls",namespace="app02")), ]
app01.urls:
urlpatterns = [ url(r'^index/', index,name="index"), ]
app02.urls:
urlpatterns = [ url(r'^index/', index,name="index"), ]
app01.views
from django.core.urlresolvers import reverse def index(request): return HttpResponse(reverse("app01:index")) app02.views from django.core.urlresolvers import reverse def index(request): return HttpResponse(reverse("app02:index"))
url(r'^login.html$', views.Login.as_view()), ============================ from django.views import View class Login(View): def dispatch(self, request, *args, **kwargs): print('before') obj = super(Login,self).dispatch(request, *args, **kwargs) print('after') return obj def get(self,request): return render(request,'login.html') def post(self,request): print(request.POST.get('user')) return HttpResponse('Login.post')
一個視圖函數,簡稱視圖,是一個簡單的Python 函數,它接受Web請求而且返回Web響應。響應能夠是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片. . . 是任何東西均可以。不管視圖自己包含什麼邏輯,都要返回響應。代碼寫在哪裏也無所謂,只要它在你的Python目錄下面。除此以外沒有更多的要求了——能夠說「沒有什麼神奇的地方」。爲了將代碼放在某處,約定是將視圖放置在項目或應用程序目錄中的名爲views.py的文件中。
下面是一個返回當前日期和時間做爲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)
讓咱們逐行閱讀上面的代碼:
l 首先,咱們從 django.http模塊導入了HttpResponse類,以及Python的datetime庫。
l 接着,咱們定義了current_datetime函數。它就是視圖函數。每一個視圖函數都使用HttpRequest對象做爲第一個參數,而且一般稱之爲request。
l 注意,視圖函數的名稱並不重要;不須要用一個統一的命名方式來命名,以便讓Django識別它。咱們將其命名爲current_datetime,是由於這個名稱可以精確地反映出它的功能。
l 這個視圖會返回一個HttpResponse對象,其中包含生成的響應。每一個視圖函數都負責返回一個HttpResponse對象。
######################views.py############################### from django.shortcuts import render,HttpResponse # Create your views here. def year(request): # request參數請求全部的參數,這個參數必定要有 return HttpResponse("ok") #每個視圖函數必須有return def year2(request,year): print(year) return HttpResponse("hello") #返回的必定是一個字符串,若是你想return純字符串,就用HttpResponse方法 def year_month(request,year,month): print(year,month) # 返回的是匹配的年和月拼接的結果 return HttpResponse(year+month) # def year_month_hasname(request,month,year): # return HttpResponse("ok") print(year,month) return HttpResponse("month是:%s,year是:%s"%(month,year))
注意:視圖會返回一個HttpResponse對象,其中包含生成的響應。每一個視圖函數都負責返回一個HttpResponse對象。
屬性: django將請求報文中的請求行、首部信息、內容主體封裝成 HttpRequest 類中的屬性。 除了特殊說明的以外,其餘均爲只讀的。 ''' 1.HttpRequest.body 一個字符串,表明請求報文的主體。在處理非 HTTP 形式的報文時很是有用,例如:二進制圖片、XML,Json等。 可是,若是要處理表單數據的時候,推薦仍是使用 HttpRequest.POST 。 另外,咱們還能夠用 python 的類文件方法去操做它,詳情參考 HttpRequest.read() 。 2.HttpRequest.path 一個字符串,表示請求的路徑組件(不含域名)。 例如:"/music/bands/the_beatles/" 3.HttpRequest.method 一個字符串,表示請求使用的HTTP 方法。必須使用大寫。 例如:"GET"、"POST" 4.HttpRequest.encoding 一個字符串,表示提交的數據的編碼方式(若是爲 None 則表示使用 DEFAULT_CHARSET 的設置,默認爲 'utf-8')。 這個屬性是可寫的,你能夠修改它來修改訪問表單數據使用的編碼。 接下來對屬性的任何訪問(例如從 GET 或 POST 中讀取數據)將使用新的 encoding 值。 若是你知道表單數據的編碼不是 DEFAULT_CHARSET ,則使用它。 5.HttpRequest.GET 一個相似於字典的對象,包含 HTTP GET 的全部參數。詳情請參考 QueryDict 對象。 6.HttpRequest.POST 一個相似於字典的對象,若是請求中包含表單數據,則將這些數據封裝成 QueryDict 對象。 POST 請求能夠帶有空的 POST 字典 —— 若是經過 HTTP POST 方法發送一個表單,可是表單中沒有任何的數據,QueryDict 對象依然會被建立。 所以,不該該使用 if request.POST 來檢查使用的是不是POST 方法;應該使用 if request.method == "POST" 另外:若是使用 POST 上傳文件的話,文件信息將包含在 FILES 屬性中。 7.HttpRequest.REQUEST 一個相似於字典的對象,它首先搜索POST,而後搜索GET,主要是爲了方便。靈感來自於PHP 的 $_REQUEST。 例如,若是 GET = {"name": "john"} 而 POST = {"age": '34'} , REQUEST["name"] 將等於"john", REQUEST["age"] 將等於"34"。 強烈建議使用 GET 和 POST 而不要用REQUEST,由於它們更加明確。 8.HttpRequest.COOKIES 一個標準的Python 字典,包含全部的cookie。鍵和值都爲字符串。 9.HttpRequest.FILES 一個相似於字典的對象,包含全部的上傳文件信息。 FILES 中的每一個鍵爲<input type="file" name="" /> 中的name,值則爲對應的數據。 注意,FILES 只有在請求的方法爲POST 且提交的<form> 帶有enctype="multipart/form-data" 的狀況下才會 包含數據。不然,FILES 將爲一個空的相似於字典的對象。 10.HttpRequest.META 一個標準的Python 字典,包含全部的HTTP 首部。具體的頭部信息取決於客戶端和服務器,下面是一些示例: CONTENT_LENGTH —— 請求的正文的長度(是一個字符串)。 CONTENT_TYPE —— 請求的正文的MIME 類型。 HTTP_ACCEPT —— 響應可接收的Content-Type。 HTTP_ACCEPT_ENCODING —— 響應可接收的編碼。 HTTP_ACCEPT_LANGUAGE —— 響應可接收的語言。 HTTP_HOST —— 客服端發送的HTTP Host 頭部。 HTTP_REFERER —— Referring 頁面。 HTTP_USER_AGENT —— 客戶端的user-agent 字符串。 QUERY_STRING —— 單個字符串形式的查詢字符串(未解析過的形式)。 REMOTE_ADDR —— 客戶端的IP 地址。 REMOTE_HOST —— 客戶端的主機名。 REMOTE_USER —— 服務器認證後的用戶。 REQUEST_METHOD —— 一個字符串,例如"GET" 或"POST"。 SERVER_NAME —— 服務器的主機名。 SERVER_PORT —— 服務器的端口(是一個字符串)。 從上面能夠看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 以外,請求中的任何 HTTP 首部轉換爲 META 的鍵時, 都會將全部字母大寫並將鏈接符替換爲下劃線最後加上 HTTP_ 前綴。 因此,一個叫作 X-Bender 的頭部將轉換成 META 中的 HTTP_X_BENDER 鍵。 11.HttpRequest.user 一個 AUTH_USER_MODEL 類型的對象,表示當前登陸的用戶。 若是用戶當前沒有登陸,user 將設置爲 django.contrib.auth.models.AnonymousUser 的一個實例。你能夠經過 is_authenticated() 區分它們。 例如: if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users. user 只有當Django 啓用 AuthenticationMiddleware 中間件時纔可用。 ------------------------------------------------------------------------------------- 匿名用戶 class models.AnonymousUser django.contrib.auth.models.AnonymousUser 類實現了django.contrib.auth.models.User 接口,但具備下面幾個不一樣點: id 永遠爲None。 username 永遠爲空字符串。 get_username() 永遠返回空字符串。 is_staff 和 is_superuser 永遠爲False。 is_active 永遠爲 False。 groups 和 user_permissions 永遠爲空。 is_anonymous() 返回True 而不是False。 is_authenticated() 返回False 而不是True。 set_password()、check_password()、save() 和delete() 引起 NotImplementedError。 New in Django 1.8: 新增 AnonymousUser.get_username() 以更好地模擬 django.contrib.auth.models.User。 12.HttpRequest.session 一個既可讀又可寫的相似於字典的對象,表示當前的會話。只有當Django 啓用會話的支持時纔可用。 完整的細節參見會話的文檔。 13.HttpRequest.resolver_match 一個 ResolverMatch 的實例,表示解析後的URL。這個屬性只有在 URL 解析方法以後才設置,這意味着它在全部的視圖中能夠訪問, 可是在 URL 解析發生以前執行的中間件方法中不能夠訪問(好比process_request,但你可使用 process_view 代替)。 '''
''' 1.HttpRequest.get_host() 根據從HTTP_X_FORWARDED_HOST(若是打開 USE_X_FORWARDED_HOST,默認爲False)和 HTTP_HOST 頭部信息返回請求的原始主機。 若是這兩個頭部沒有提供相應的值,則使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有詳細描述。 USE_X_FORWARDED_HOST:一個布爾值,用於指定是否優先使用 X-Forwarded-Host 首部,僅在代理設置了該首部的狀況下,才能夠被使用。 例如:"127.0.0.1:8000" 注意:當主機位於多個代理後面時,get_host() 方法將會失敗。除非使用中間件重寫代理的首部。 2.HttpRequest.get_full_path() 返回 path,若是能夠將加上查詢字符串。 例如:"/music/bands/the_beatles/?print=true" 3.HttpRequest.build_absolute_uri(location) 返回location 的絕對URI。若是location 沒有提供,則使用request.get_full_path()的返回值。 若是URI 已是一個絕對的URI,將不會修改。不然,使用請求中的服務器相關的變量構建絕對URI。 例如:"http://example.com/music/bands/the_beatles/?print=true" 4.HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None) 返回簽名過的Cookie 對應的值,若是簽名再也不合法則返回django.core.signing.BadSignature。 若是提供 default 參數,將不會引起異常並返回 default 的值。 可選參數salt 能夠用來對安全密鑰強力攻擊提供額外的保護。max_age 參數用於檢查Cookie 對應的時間戳以確保Cookie 的時間不會超過max_age 秒。 複製代碼 >>> request.get_signed_cookie('name') 'Tony' >>> request.get_signed_cookie('name', salt='name-salt') 'Tony' # 假設在設置cookie的時候使用的是相同的salt >>> request.get_signed_cookie('non-existing-cookie') ... KeyError: 'non-existing-cookie' # 沒有相應的鍵時觸發異常 >>> request.get_signed_cookie('non-existing-cookie', False) False >>> request.get_signed_cookie('cookie-that-was-tampered-with') ... BadSignature: ... >>> request.get_signed_cookie('name', max_age=60) ... SignatureExpired: Signature age 1677.3839159 > 60 seconds >>> request.get_signed_cookie('name', False, max_age=60) False 複製代碼 5.HttpRequest.is_secure() 若是請求時是安全的,則返回True;即請求通是過 HTTPS 發起的。 6.HttpRequest.is_ajax() 若是請求是經過XMLHttpRequest 發起的,則返回True,方法是檢查 HTTP_X_REQUESTED_WITH 相應的首部是不是字符串'XMLHttpRequest'。 大部分現代的 JavaScript 庫都會發送這個頭部。若是你編寫本身的 XMLHttpRequest 調用(在瀏覽器端),你必須手工設置這個值來讓 is_ajax() 能夠工做。 若是一個響應須要根據請求是不是經過AJAX 發起的,而且你正在使用某種形式的緩存例如Django 的 cache middleware, 你應該使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 裝飾你的視圖以讓響應可以正確地緩存。 7.HttpRequest.read(size=None) 像文件同樣讀取請求報文的內容主體,一樣的,還有如下方法可用。 HttpRequest.readline() HttpRequest.readlines() HttpRequest.xreadlines() 其行爲和文件操做中的同樣。 HttpRequest.__iter__():說明可使用 for 的方式迭代文件的每一行。'''
注意:鍵值對的值是多個的時候,好比checkbox類型的input標籤,select標籤,須要用:
request.POST.getlist("hobby")
render(request, template_name[, context])
結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象。
參數:
request: 用於生成響應的請求對象。
template_name:要使用的模板的完整名稱,可選的參數
context:添加到模板上下文的一個字典。默認是一個空字典。若是字典中的某個值是可調用的,視圖將在渲染模板以前調用它。
content_type:生成的文檔要使用的MIME類型。默認爲DEFAULT_CONTENT_TYPE 設置的值。
status:響應的狀態碼。默認爲200。
參數能夠是:
l 一個模型:將調用模型的get_absolute_url() 函數
l 一個視圖,能夠帶有參數:將使用urlresolvers.reverse 來反向解析名稱
l 一個絕對的或相對的URL,將原封不動的做爲重定向的位置。
默認返回一個臨時的重定向;傳遞permanent=True 能夠返回一個永久的重定向。
示例:
你能夠用多種方式使用redirect() 函數。
將調用get_absolute_url() 方法來獲取重定向的URL:
from django.shortcuts import redirect def my_view(request): ... object = MyModel.objects.get(...) return redirect(object)
能夠帶有位置參數和關鍵字參數;將使用reverse() 方法反向解析URL:
def my_view(request): ... return redirect('some-view-name', foo='bar')
def my_view(request): ... return redirect('/some/url/')
也能夠是一個完整的URL:
def my_view(request): ... return redirect('http://example.com/')
默認狀況下,redirect() 返回一個臨時重定向。以上全部的形式都接收一個permanent 參數;若是設置爲True,將返回一個永久的重定向:
def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True)
-----------------------------------url.py url(r"login", views.login), url(r"yuan_back", views.yuan_back), -----------------------------------views.py def login(req): if req.method=="POST": if 1: # return redirect("/yuan_back/") name="yuanhao" return render(req,"my backend.html",locals()) return render(req,"login.html",locals()) def yuan_back(req): name="苑昊" return render(req,"my backend.html",locals()) -----------------------------------login.html <form action="/login/" method="post"> <p>姓名<input type="text" name="username"></p> <p>性別<input type="text" name="sex"></p> <p>郵箱<input type="text" name="email"></p> <p><input type="submit" value="submit"></p> </form> -----------------------------------my backend.html <h1>用戶{{ name }}你好</h1>
redirect關鍵點:兩次請求過程,掌握流程。
注意:render和redirect的區別:
一、 if 頁面須要模板語言渲染,須要的將數據庫的數據加載到html,那麼render方法則不會顯示這一部分。
二、 the most important: url沒有跳轉到/yuan_back/,而是還在/login/,因此當刷新後又得從新登陸。
python的模板:HTML代碼+模板語法
模版包括在使用時會被值替換掉的 變量,和控制模版邏輯的 標籤。
def current_time(req): # ================================原始的視圖函數 # import datetime # now=datetime.datetime.now() # html="<html><body>如今時刻:<h1>%s.</h1></body></html>" %now # ================================django模板修改的視圖函數 # from django.template import Template,Context # now=datetime.datetime.now() # t=Template('<html><body>如今時刻是:<h1>{{current_date}}</h1></body></html>') # #t=get_template('current_datetime.html') # c=Context({'current_date':str(now)}) # html=t.render(c) # # return HttpResponse(html) #另外一種寫法(推薦) import datetime now=datetime.datetime.now() return render(req, 'current_datetime.html', {'current_date':str(now)[:19]})
模板語法:目的是將變量(數據庫的內容)如何巧妙的嵌入到html頁面中(就不用以前咱們用的字符串拼接了)
在 Django 模板中遍歷複雜數據結構的關鍵是句點字符 .
語法:
{{var_name}}
#####################view.py############################## def index(request): import datetime s="hello" l=[111,222,333] # 列表 dic={"name":"yuan","age":18} # 字典 date = datetime.date(1993, 5, 2) # 日期對象 class Person(object): def __init__(self,name): self.name=name person_yuan=Person("yuan") # 自定義類對象 person_egon=Person("egon") person_alex=Person("alex") person_list=[person_yuan,person_egon,person_alex] return render(request,"index.html",{"l":l,"dic":dic,"date":date,"person_list":person_list})
template:
<h4>{{s}}</h4> <h4>列表:{{ l.0 }}</h4> <h4>列表:{{ l.2 }}</h4> <h4>字典:{{ dic.name }}</h4> <h4>日期:{{ date.year }}</h4> <h4>類對象列表:{{ person_list.0.name }}</h4>
注意:句點符也能夠用來引用對象的方法(無參數方法)。
<h4>字典:{{ dic.name.upper }}</h4>
需求:當用戶輸入一個URL: http://127.0.0.1:8080/timer,就返回給用戶一個當前的時間
基本流程
model:模型,和數據庫相關的
template:模板,存放html文件,模板語法(目的是將變量如何巧妙的嵌入到HTML頁面中)。
views:視圖函數
另加urls:url路徑與視圖函數的映射關係,,能夠不是一一對應的。
建立一個Django項目:django-admin startproject projectname
建立一個項目下的應用:python3 manage.py startapp appname
運行:python3 manage.py runserver IP PORT
功能:創建起url與視圖函數的映射關係
url(正則表達式(規則),視圖函數,[可選參數])
url:http://127.0.0.1:8080/blog/articles/2003/05?a=1&b=2
匹配字符串:用戶輸入的url對應的路徑 /blog/articles/2003/05
注意:
(1)出現覆蓋現象的狀況,也就是匹配規則衝突的時候,匹配第一個url
(2)無名分組:url(r'^articles/(\d{4})/(\d{2})$', views.year_month), # year(requset,1990,12) 按位置傳參數
(3)有名分組:url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})$', views.year_month), # year(requset,year=1990,month=12) 按位置傳參數
(4)url分發:url(r'^blog/',include('blog.urls'))
一、視圖函數:必定是要包含兩個對象的(render源碼裏面有HttpResponse對象)
request對象:-----》全部的請求信息
HttpResponse:-----》響應的內容(字符串)
二、get請求發送數據:http://127.0.0.1:8000/login.html?user=asd&pwd=asd
重點:request裏包含哪些數據 1、request.GET: GET請求的數據,若是沒有數據是一個空字典 {} 2、request.POST:POST請求的數據 ,若是沒有數據是一個空字典 {} 3、request.method:請求方式:GET 或 POST 四、請求某個鍵下多個值時:request.POST.getlist("hobby") 5、 request.path : 請求路徑(只會拿到路徑,不拿數據) 請求url:http://127.0.0.1:8000/index.html/23?a=1 path:request.path:/index.html/23 6、request.get_full_path():請求路徑(路徑和數據都會拿到) 請求url:http://127.0.0.1:8000/index.html/23?a=1 request.get_full_path():/index.html/23?a=1
render:只會返回頁面內容,可是未發送第二次請求
redirect:發揮了第二次請求,url更新
具體實例說明以下:
在使用Django 項目時,一個常見的需求是得到URL 的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。
人們強烈但願不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 絕不相關的專門的URL 生成機制,由於這樣容易致使必定程度上產生過時的URL。
換句話講,須要的是一個DRY 機制。除了其它有點,它還容許設計的URL 能夠自動更新而不用遍歷項目的源代碼來搜索並替換過時的URL。
獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型(位置參數、關鍵字參數)和值。
Django 提供一個辦法是讓URL 映射是URL 設計惟一的地方。你填充你的URLconf,而後能夠雙向使用它:
l 根據用戶/瀏覽器發起的URL 請求,它調用正確的Django 視圖,並從URL 中提取它的參數須要的值。
l 根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的URL。
第一種方式是咱們在前面的章節中一直討論的用法。第二種方式叫作反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查。
在須要URL 的地方,對於不一樣層級,Django 提供不一樣的工具用於URL 反查:
l 在模板中:使用url 模板標籤。
l 在Python 代碼中:使用django.core.urlresolvers.reverse() 函數。
l 在更高層的與處理Django 模型實例相關的代碼中:使用get_absolute_url() 方法。
考慮下面的URLconf:
from django.conf.urls import url from . import views urlpatterns = [ #... url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'), #... ]
根據這裏的設計,某一年nnnn對應的歸檔的URL是/articles/nnnn/。
你能夠在模板的代碼中使用下面的方法得到它們:
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a> <ul> {% for yearvar in year_list %} <li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li> {% endfor %} </ul>
在Python 代碼中,這樣使用:
from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect def redirect_to_year(request): # ... year = 2006 # ... return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
若是出於某種緣由決定按年歸檔文章發佈的URL應該調整一下,那麼你將只須要修改URLconf 中的內容。
在某些場景中,一個視圖是通用的,因此在URL 和視圖之間存在多對一的關係。對於這些狀況,當反查URL 時,只有視圖的名字還不夠。
例子中:
分析:想咱們一開始寫的硬編碼,也就是吧action要跳轉的路徑寫死了。可是像淘寶,天貓等都會常常更新新東西,,那麼你的頁面上的url路徑也會時不時的變化。可是若是有特別多的商品,那麼你就得去服務端一個一個的改,這樣顯得很麻煩,那麼有沒有一種機制幫咱們解決問題呢?那就按照我下面的辦法解決。就把url路徑寫活了。
一、首先給url起一個別名。
二、而後在login.html中寫上{% url ‘別名’’ %} ,若是在頁面中點擊查看元素,它會變成login.html,,,固然個人是分發了,,就會變成test/login.html
三、這樣你就能夠修改你的正則了,,由於他是按照別名走的,不會影響。
urls.py
login.html
查看元素的結果:
這樣的好處是:不管你怎麼改你要匹配的url,只要你寫上了別名。在html實現了模板語法,就會去找別名對應的那個url,之後無論你怎麼改url都沒事,就寫活了,就不像一開始寫的硬編碼了。
只要是在html裏面有模板語法就不是html文件了,這樣的文件就叫作模板。
在 Django 模板中遍歷複雜數據結構的關鍵是句點字符 .(也就是點)
views.py
def index(request): name = "hello haiyan" i = 200 l = [11,22,33,44,55] d = {"name":"haiyan","age":20} class People(object): #繼承元類 def __init__(self,name,age): self.name = name self.age = age def __str__(self): return self.name+str(self.age) def dream(self): return "你有夢想嗎?" #實例化 person_egon = People("egon",10) person_dada = People("dada",34) person_susan = People("susan",34) person_list = [person_dada,person_egon,person_susan] return render(request,"index.html", { "name":name, "i":i, "l":l, "d":d, #鍵對應的是模板裏的名字。值對應的是上面定義的變量 "person_egon":person_egon, "person_dada":person_dada, "person_list":person_list, } ) # return render(request,"index.html",locals()) #用locals()能夠不用寫上面的render了。不過用locals(),views裏面用什麼名。模板裏面就得用什麼名 # locals()局部的:用了locals就至關於都得按照上面的那樣
template/index.html
<h4>變量{{ z }}:深度查詢</h4><hr> <h3>{{ name }}</h3> <p>{{ i }}</p> <p>{{ l }}</p> <p>{{ d }}</p> <p>{{ l.0 }}------》取單個值可經過句點符(也就是點)</p> <p>{{ l.4 }}</p> <p>{{ d.name }}</p> <p>{{ d.age }}-----》字典也能夠根據句點符取值,一個點就搞定了。 然而在前端頁面中是看不到你的模板語法的,當你點擊審查元素的 時候,你就會發現,偷偷的換過來了</p> <p>{{ person_dada.name }}</p> <p>{{ person_egon.age }}</p> <p>{{ person_dada.dream }}</p> <!-- .方法的時候,注意當前的dream方法是沒有參數的--> <p>{{ person_list.2 }}</p> <!--單個取值--> <p>{{ person_list.1.name }}</p> <!-- 那怎麼讓對象變成字符串呢?在index視圖函數裏裏面再加上一個__str__內置方法--> <!--__str__是對象字符串的改變-->
注意:句點符也能夠用來引用對象的方法(無參數方法)。
<h4>字典:{{ dic.name.upper }}</h4>
標籤看起來像是這樣的: {% tag %}。標籤比變量更加複雜:一些在輸出中建立文本,一些經過循環或邏輯來控制流程,一些加載其後的變量將使用到的額外信息到模版中。
一些標籤須要開始和結束標籤 (例如{% tag %} ...標籤 內容 ... {% endtag %})。
1、for標籤(注:循環序號能夠經過{{forloop}}顯示)
<h3>循環取值1</h3><hr> {% for item in person_list %} <p>{{ item.name }},{{ item.age }}</p> {% endfor %} <h3>循環取值2:倒序</h3><hr> {% for item in person_list reversed %} <!--序號從1開始--> <p>{{ forloop.counter }}----->{{ item.name }},{{ item.age }}</p> <!--序號從0開始--><p>{{ forloop.counter0 }}----->{{ item.name }},{{ item.age }}</p><!-- 序號倒序 --><p>{{ forloop.revcounter }}----->{{ item.name }},{{ item.age }}</p> {% endfor %} <h3>循環取值3:字典</h3><hr> {% for k,v in d.items %} <p>{{ k }},{{ v}}</p> {% endfor %}
2、for....empty :for 標籤帶有一個可選的{% empty %} 從句,以便在給出的組是空的或者沒有被找到時,能夠有所操做。
{% for person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>sorry,no person here</p> {% endfor %}
3、if標籤 :{% if %}會對一個變量求值,若是它的值是「True」(存在、不爲空、且不是boolean類型的false值),對應的內容塊會輸出。
{% if i > 300 %} <p>大於{{ i }}</p> {% elif i == 200 %} <p>等於{{ i }}</p> {% else %} <p>小於{{ i }}</p> {% endif %}
4、with:使用一個簡單地名字緩存一個複雜的變量,當你須要使用一個「昂貴的」方法(好比訪問數據庫)不少次的時候是很是有用的
{% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %} <p>{{ person_list.2.name }}</p> {% with name=person_list.2.name %} <p>{{ name }}</p> {% endwith %}
5、csrf_token:這個標籤用於跨站請求僞造保護
提交數據的時候就會作安全機制,當你點擊提交的時候會出現一個forbbiddon的錯誤,就是用setting配置裏的scrf作安全機制的,那麼咱們能夠把它給註釋了,或者在form表單下面添加一個{% csrf_token %} ,這纔是真正解決的辦法,註釋不是解決的辦法
<h3>scrf_token</h3><form action="/tag/" method="post"> {% csrf_token %} <p><input type="text" name="haiyan"></p> <input type="submit"> </form>
一、default:
若是一個變量是false或者爲空,使用給定的默認值。不然,使用變量的值。例如:
<p>default過濾器:{{ li|default:"若是顯示爲空,設置的解釋性的內容" }}</p>
2、length:返回值的長度。它對字符串和列表都起做用。例如:
{{ value|length }}
若是 value 是 ['a', 'b', 'c', 'd'],那麼輸出是 4。
三、filesizeformat:
將值格式化爲一個 「人類可讀的」 文件尺寸(例如 '13 KB'
, '4.1 MB'
, '102 bytes'
, 等等)。例如:
{{ value|filesizeformat }}
若是 value
是 123456789,輸出將會是 117.7 MB
。
4、date:若是 value=datetime.datetime.now()
{{ value|date:"Y-m-d" }}
5、slice :切片
若是 value="hello world"
{{ value|slice:"2:-1" }}
6、truncatechars 截斷
若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。
參數:要截斷的字符數
例如:
<p>截斷字符:{{ content|truncatechars:20 }}</p> <p>截斷單詞:{{ content|truncatewords:4 }}</p>
若是content是「I am is haiyan,how are you asd df dfgfdgdg?
輸出結果: 截斷字符:I am is haiyan,ho...
輸出結果 :截斷單詞:I am is haiyan,how ...
7、safe
Django的模板中會對HTML標籤和JS等語法標籤進行自動轉義,緣由顯而易見,這樣是爲了安全。可是有的時候咱們可能不但願這些HTML元素被轉義,好比咱們作一個內容管理系統,後臺添加的文章中是通過修飾的,這些修飾多是經過一個相似於FCKeditor編輯加註了HTML修飾符的文本,若是自動轉義的話顯示的就是保護HTML標籤的源文件。爲了在Django中關閉HTML的自動轉義有兩種方式,若是是一個單獨的變量咱們能夠經過過濾器「|safe」的方式告訴Django這段代碼是安全的沒必要轉義。好比:
value="<a href="">點擊</a>" {{ value|safe}} <p>{{ label }}</p> <!--爲了安全系統會把標籤變成字符串--> <p>{{ label|safe }}</p> <!--加上safe,肯定你的數據是安全的才能被當成是標籤-->
這裏簡單介紹一些經常使用的模板的過濾器,更多詳見
1、在settings中的INSTALLED_APPS配置當前app,否則django沒法找到自定義的simple_tag.
2、在app中建立templatetags模塊(模塊名只能是templatetags)
3、在templatetags裏面建立任意 .py 文件,
如:my_tags.py
from django import template from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改變 @register.filter 過濾器 def multi(x,y): return x*y @register.simple_tag 標籤 def multitag(x,y,z): return x*y*z @register.simple_tag 標籤 def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
4、在使用自定義simple_tag和filter的html文件中導入以前建立的 my_tags.py
{% load my_tags %}
5、使用simple_tag和filter(如何調用)
過濾器: {{ var|filter_name:參數 }} # 參數只能是兩個,一個參數是變量var ,一個是參數是後面的那個參數
標籤: {% simple_tag 參數1 參數2 ... %}
-------------------------------.html {% load xxx %} # num=12 {{ num|multi:2 }} #24 {{ num|multi:"[22,333,4444]" }} 至關於複製了,吧[22,333,4444]乘了num遍 {% multitag 2 5 6 %} 參數不限,但不能放在if for語句中 {% simple_tag_multi num 5 %}
自定義過濾器函數的參數只能兩個,能夠進行邏輯判斷
自定義標籤無參數限制,不能進行邏輯判斷
{% if i|multi:5 > 1000 %} <!-- 判斷i*5>1000 --> <p>大於{{ i }}</p> {% else %} <p>大於等於{{ i }}</p> {% endif %}
目的是:減小代碼的冗餘
語法:
{% block classinfo %}
{% endblock %}
一、建立一個base.html文件,
二、把要顯示的頁面的內容寫在這裏面,也就是html要在瀏覽器顯示的內容
三、在right裏面寫個盒子
{% block classinfo %}
{% endblock %}
在這裏面寫個空盒子,之後誰來擴展就在這個盒子裏面添加相應的內容就好了
四、而後再建立一個.html文件,讓這個繼承base.html文件,
{% extends "base.html" %} #必須是在文件的第一行
在基板裏面添加內容
{% block classinfo %}
<h2>首頁</h2>
<h2>學生信息</h2>
<h3>{{ class_id }}班</h3>
{% endblock%}
五、也能夠寫好多盒子,
在left中寫個盒子
{% block menu %}
<p>I see you you</p>
{% endblock %}
注意:
盒子裏面能夠有默認的內容,若是有默認的時候你不擴展就走默認的,若是你擴展了,就替換了,那麼不替換直接追加能夠嘛?能夠的,那就用下面的方式。
{% block.super %}
例如:
{% block menu %} {{ block.super }} <p>!!!</p> #先繼承父類的,後插入數據 {% endblock %}
一、模板繼承圍繞兩點:繼承和擴展
你有什麼繼承什麼,
擴展的是盒子,
二、模板中設置的盒子越多越好,由於這樣你想擴展的時候就容易了。我想擴展就擴展了。不擴展就不擴展了
三、爲了更好的可讀性,你也能夠給你的 {% endblock %} 標籤一個 名字 。例如:
{% block content %}
...
{% endblock content %}
四、若是你發現你本身在大量的模版中複製內容,那可能意味着你應該把內容移動到父模版中的一個 {% block %} 中。
最後,請注意你並不能在一個模版中定義多個相同名字的 block 標籤。這個限制的存在是由於block標籤的做用是「雙向」的。這個意思是,block標籤不只提供了一個坑去填,它還在 _父模版_中定義了填坑的內容。若是在一個模版中有兩個名字同樣的 block 標籤,模版的父模版將不知道使用哪一個block的內容。
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^text/(\d+)', views.text), ]
from django.shortcuts import render,redirect # Create your views here. def text(request,class_id): # 班級變量 print(class_id) #拿到的是你在路徑裏輸入的幾就是幾 # 數據庫查詢 return render(request, "text.html", {"class_id": class_id})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width"> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <title>Title</title> <style> .right { height: 400px; background-color: silver; } </style> </head> <body> {#導航條#} <nav class="navbar navbar-primary navbar-inverse"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Brand</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> <li role="separator" class="divider"></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> {#內容#} <div class="containers"> <div class="row"> <div class="col-md-11 col-lg-offset-1"> {# 左側#} <div class="left col-md-3"> {% block menu %} <div class="list-group"> <a href="#" class="list-group-item active"> 學生班級 </a> <a href="/text/6" class="list-group-item">s6</a> <a href="/text/7" class="list-group-item">s7</a> <a href="/text/8" class="list-group-item">s8</a> <a href="/text/9" class="list-group-item">s9</a> </div> {% endblock %} </div> {# 右側#} <div class="right col-md-8"> {# 定義一個盒子#} {% block classinfo %} {% endblock %} </div> </div> </div> </div> {#底部#} </body> </html>
{% extends "base.html" %} {% block classinfo %} <h1>學生信息</h1> <h3>{{ class_id }}班級</h3> {% endblock %} {#追加#} {% block menu %} {{ block.super }} <a href="">學生信息</a> {% endblock %}
咱們本身導入的一些包就叫作靜態文件
一、在全局中先建立一個static的包,
二、在static裏面導入咱們的bootstrap,仍是jquery等
三、而後在settings.py中加上一些配置
STATIC_URL = '/static/' #這個配置就至關於下面配置的別名,若是這裏的名字修改了就按照這裏的名字去導入 STATICFILES_DIRS = [ os.path.join(BASE_DIR,"static") #E:\day68\static 找到static路徑 ]
四、導入css,js,jquery
<link rel = "stysheet",href= "/static/index.css/"> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
映射關係:
表名 --------------------》類名
字段--------------------》屬性
表記錄-----------------》類實例化對象
ORM的兩大功能:
操做表:
- 建立表
- 修改表
- 刪除表
操做數據行:
- 增刪改查
ORM利用pymysql第三方工具連接數據庫
Django沒辦法幫咱們建立數據庫,只能咱們建立完以後告訴它,讓django去連接
1、本身建立數據庫
2、在settings裏面配置mysql數據庫連接
sqlite3------改成mysql
# 修改django默認的數據庫的sqlite3爲mysql DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', #經過這個去連接mysql 'NAME': 'djangotsgl', 'USER':'root', 'PASSWORD':'123456', 'HOST':'localhost', 'PORT':'3306', } }
這樣寫上之後django會默認的就去連接數據庫,這時你會看到報錯了,那麼解決的辦法就是下面的這樣。
3、app01中的--init--文件
import pymysql pymysql.install_as_MySQLdb()
4、建立數據庫表
models.py
class Book(models.Model): #必需要繼承的 nid = models.AutoField(primary_key=True) #自增id(能夠不寫,默認會有自增id) title = models.CharField(max_length=32) publishDdata = models.DateField() #出版日期 author = models.CharField(max_length=32) price = models.DecimalField(max_digits=5,decimal_places=2) #一共5位,保留兩位小數
執行命令建立:(須要記住的!!!)
python3 manage.py makemigrations 建立腳本
python3 manage.py migrate 遷移
#######################圖片內容具體####################### <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> <style> table{ margin-top: 50px; } </style> </head> <body> <div class="containers"> <div class="row"> <div class="col-md-9 col-md-offset-2"> <table class="table table-hover"> <thead> <tr> <th>編號</th> <th>書名</th> <th>出版日期</th> <th>做者</th> <th>價錢</th> <th>操做</th> </tr> </thead> <tbody> {% for book in book_list %} <tr> <td>{{ book.nid }}</td> <td>{{ book.title }}</td> <td>{{ book.publishDdata|date:'Y-m-d' }}</td> <td>{{ book.author }}</td> <td>{{ book.price }}</td> <td> <a href="/del/{{ book.nid }}"><button class="btn btn-danger">刪除</button></a> <a href="/edit/{{ book.nid }}"><button class="btn btn-success">編輯</button></a> <a href="/add/"><button class="btn btn-primary">添加</button></a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> </html>
5、查看數據庫的sql語句(加在settings.py)
查看數據庫執行代碼 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
class Class(models.Model): name = models.CharField(max_length=32,verbose_name="班級名") course = models.CharField(verbose_name="課程",max_length=32) def __str__(self): return self.name class Teacher(models.Model): name = models.CharField(max_length=23,verbose_name="姓名") classes = models.ManyToManyField(verbose_name="所屬班級",to="Class") def __str__(self): return self.name
# 方式一:基於對象的查找 obj = models.Teacher.objects.filter(name="娜娜").first() print(obj.classes.all()) print("娜娜老師帶的班級",obj.classes.values("name")) # 方式二:基於雙下劃線的查找 obj_cls = models.Teacher.objects.filter(name="娜娜").values("classes__name") print("娜娜老師帶的班級",obj_cls)
注意:要說明的是多對多的查詢用.all,查單個的時候用.values或者values_list,不要用obj.classes.name,這樣查到的會是None,反向查詢也是如此。我就是犯了這樣的錯,引覺得戒。。
總結:無論是一對多,仍是多對多,要是查詢多得一方就得用all()
運行結果截圖:
表結構:
from django.db import models # Create your models here. # 一個學生有一個班級,一個班級能夠有好多學生,因此是 # 一對多的關係,關聯字段放在多的一方 class Student(models.Model): name = models.CharField(max_length=32,verbose_name="姓名") age = models.IntegerField(verbose_name="年齡") classes = models.ForeignKey(to="Class",verbose_name="所屬班級") def __str__(self): return self.name class Class(models.Model): name = models.CharField(max_length=32,verbose_name="班級名") course = models.CharField(verbose_name="課程",max_length=32) def __str__(self): return self.name class Teacher(models.Model): name = models.CharField(max_length=23,verbose_name="姓名") classes = models.ManyToManyField(verbose_name="所屬班級",to="Class") def __str__(self): return self.name
# 方式一: print("海燕所在的班級",models.Student.objects.filter(name="海燕").values("classes__name")) # 方式二: obj_cls = models.Student.objects.filter(name="海燕").first() print("海燕所在的班級",obj_cls.classes.name)
print("海燕所在班的老師的姓名",models.Student.objects.filter(name="海燕").values("classes__teacher__name"))
print("軟件測試151班的全部學生的姓名",models.Class.objects.filter(name="軟件測試151").values("student__name")) obj = models.Class.objects.filter(name="軟件測試151").first() # print("軟件測試151班的全部學生的姓名",obj.student_set.name) #這樣打印的結果是None print("軟件測試151班的全部學生的姓名",obj.student_set.all().values("name"))
一、form表單中要用submit,若是用button切記要加上type,否則button默認的type是submit,會有影響
<button class="login" type="button">註冊</button>
<button type="button" onclick="doValidation();">提交</button> <input type="button" onclick="doValidation();" value="提交"/> 上面兩種寫法是對的,功能同樣。 <button onclick="doValidation();">提交</button> 若是寫成這種,默認爲submit,原本doValidation方法裏有提交功能了, 再加上按鈕也是提交功能,會提交兩次。因此使用按鈕時最好指定type類型。
對於單表有兩種方式
# 添加數據的兩種方式 # 方式一:實例化對象就是一條表記錄 Frank_obj = models.Student(name ="海東",course="python",birth="2000-9-9",fenshu=80) Frank_obj.save() # 方式二: models.Student.objects.create(name ="海燕",course="python",birth="1995-5-9",fenshu=88)
# 查詢相關API # 一、all():查看全部 student_obj = models.Student.objects.all() print(student_obj) #打印的結果是QuerySet集合 # 二、filter():能夠實現且關係,可是或關係須要藉助Q查詢實現。。。 # 查不到的時候不會報錯 print(models.Student.objects.filter(name="Frank")) #查看名字是Frank的 print(models.Student.objects.filter(name="Frank",fenshu=80)) #查看名字是Frank的而且分數是80的 # 三、get():若是找不到就會報錯,若是有多個值,也會報錯,只能拿有一個值的 print(models.Student.objects.get(name="Frank")) #拿到的是model對象 print(models.Student.objects.get(nid=2)) #拿到的是model對象 # 四、exclude():排除條件 print( models.Student.objects.exclude(name="海東")) #查看除了名字是海東的信息 # 五、values():是QuerySet的一個方法 (吧對象轉換成字典的形式了,) print(models.Student.objects.filter(name="海東").values("nid","course")) #查看名字爲海東的編號和課程 #打印結果:<QuerySet [{'nid': 2, 'course': 'python'}, {'nid': 24, 'course': 'python'}]> # 六、values_list():是queryset的一個方法 (吧對象轉成元組的形式了) print(models.Student.objects.filter(name="海東").values_list("nid", "course")) #打印結果:< QuerySet[(2, 'python'), (24, 'python')] > # 七、order_by():排序 print(models.Student.objects.all().order_by("fenshu")) # 八、reverse():倒序 print(models.Student.objects.all().reverse()) # 九、distinct():去重(只要結果裏面有重複的) print(models.Student.objects.filter(course="python").values("fenshu").distinct()) # 十、count():查看有幾條記錄 print(models.Student.objects.filter(name="海東").count()) # 十一、first() # 十二、last() return render(request,"test.html",{"student_obj":student_obj}) # 1三、esits:查看有沒有記錄,若是有返回True,沒有返回False # 並不須要判斷全部的數據, # if models.Book.objects.all().exists():
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") #包括ven的 models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 models.Tb1.objects.filter(id__range=[1, 2]) # 範圍bettwen and startswith,istartswith, endswith, iendswith
對象能夠調用本身的屬性,用一個點就能夠 還能夠經過雙下劃線。。。 models.Book.objects.filter(price__gt=100) 價格大於100的書 models.Book.objects.filter(author__startwith= "張") 查看做者的名字是以張開頭的 主鍵大於5的且小於2 price__gte=99大於等於 publishDate__year =2017,publishDate__month = 10 查看2017年10月份的數據
注意:
<1> 第二種方式修改不能用get的緣由是:update是QuerySet對象的方法,get返回的是一個model對象,它沒有update方法,而filter返回的是一個QuerySet對象(filter裏面的條件可能有多個條件符合,好比name='alvin',可能有兩個name='alvin'的行數據)。
<2>在「插入和更新數據」小節中,咱們有提到模型的save()方法,這個方法會更新一行裏的全部列。 而某些狀況下,咱們只須要更新行裏的某幾列。
此外,update()方法對於任何結果集(QuerySet)均有效,這意味着你能夠同時更新多條記錄update()方法會返回一個整型數值,表示受影響的記錄條數。
注意,這裏由於update返回的是一個整形,因此無法用query屬性;對於每次建立一個對象,想顯示對應的raw sql,須要在settings加上日誌記錄部分
刪除方法就是 delete()。它運行時當即刪除對象而不返回任何值。例如:e.delete()
def delstudent(request,id): # 刪除數據 models.Student.objects.filter(nid=id).delete() return redirect("/test/")
你也能夠一次性刪除多個對象。每一個 QuerySet 都有一個 delete() 方法,它一次性刪除 QuerySet 中全部的對象。
例如,下面的代碼將刪除 pub_date 是2005年的 Entry 對象:
Entry.objects.filter(pub_date__year=2005).delete()
要牢記這一點:不管在什麼狀況下,QuerySet 中的 delete() 方法都只使用一條 SQL 語句一次性刪除全部對象,而並非分別刪除每一個對象。若是你想使用在 model 中自定義的 delete() 方法,就要自行調用每一個對象的delete 方法。(例如,遍歷 QuerySet,在每一個對象上調用 delete()方法),而不是使用 QuerySet 中的 delete()方法。
在 Django 刪除對象時,會模仿 SQL 約束 ON DELETE CASCADE 的行爲,換句話說,刪除一個對象時也會刪除與它相關聯的外鍵對象。例如:
b = Blog.objects.get(pk=1) # This will delete the Blog and all of its Entry objects. b.delete()
要注意的是: delete() 方法是 QuerySet 上的方法,但並不適用於 Manager 自己。這是一種保護機制,是爲了不意外地調用 Entry.objects.delete() 方法致使 全部的 記錄被誤刪除。若是你確認要刪除全部的對象,那麼你必須顯式地調用:
Entry.objects.all().delete()
編輯操做涉及到的語法 分析: 1、點擊編輯,讓跳轉到另外一個頁面,拿到我點擊的那一行 兩種取id值的方式 方式一: 利用數據傳參數(做爲數據參數傳過去了) <a href="/edit/?book_id = {{book_obj.nid}}"></a> #至關於發了一個鍵值對 url裏面就不用寫匹配的路徑了, id = request.GET.get("book_id") #取值 方式二: 利用路徑傳參,得在url裏面加上(\d+),就得給函數傳個參數,無名分組從參數裏面取值 <a href="/{{book_obj.nid}}"></a> 2、拿到id,而後在作篩選 id = request.GET.get("book_id") book_obj = models.Book.objects.filter(nid=id) #拿到的是一個列表對象 注意: 1.取[0]就拿到對象了,,而後對象.屬性就能夠取到值了 2.用get,你取出來的數據必須只有一條的時候,,若是有多條用get就會報錯,,,可是用get就不用加[0]了 book_obj = models.Book.objects.filter(nid=id)[0] 3、當點擊編輯的時候怎麼讓input框裏顯示文本內容 value = "{{book_obj.title}}" 4、改完數據後從新提交 當提交的時候走action...../edit/} 隱藏一個input, <input type="hidden" name = "book_id" value="{{book_obj.nid}}"> 判斷post的時候: 修改數據 方式一:save(這種方式效率是很是低的,不推薦使用,瞭解就好了) 修改的前提是先取(拿到要編輯的id值) id = request.POST.get("book_id") bk_obj = models.Book.objects.filter(nid=id)[0] bk_obj.title = "hhhhhh" #這是寫死了,不能都像這樣寫死了 bk_obj.save() 只要是用對象的這種都要.save 方式二:update title = request.POST.get("title") models.Book.objects.filter(nid=id).update(title=title,......) 跳轉到index 若是是post請求的時候怎麼找到id呢, 1、若是是數據傳參:(也就是get請求的時候) 能夠經過一個隱藏的input框,給這個框給一個name屬性,value屬性。經過request.POST.get("鍵"),,就能夠獲得id的值 2、若是是路徑傳參 能夠經過傳參的形式,當正則表達式寫一個(\d+)的時候,就給函數傳一個id,可經過這個id知道id.
做業要求,在Django裏面實現一個簡單的表單數據查詢、新增、修改、刪除等。