[TOC]html
orm表關係如何創建
一對一
一張表的字段信息太多,能夠人爲分出一張表前端
一對多
外鍵字段建在 多的那一方python
多對多
多對多的外鍵關係須要創建第三張表來專門處理git
以圖書館裏系統爲例,建立圖書表,做者表,出版社表正則表達式
以圖書管理系統爲例,在django orm 創建表關係:數據庫
- 一對一的表關係,外鍵字段建在任意一方均可以,可是建議建在查詢頻率較高的一方
- 書與出版社是一對多關係,而且書是多的一方,因此外鍵字段建在書表中
- 書與做者是多對多的關係, 外鍵字段建在任意一方均可以,建議建在查詢頻率較高的一方
class Book(models.Model): title = models.CharField(max_length=32) # 小數總共八位,小數佔兩位 price = models.DecimalField(max_digits=8, decimal_places=2) # 書與出版社是一對多關係,而且書是多的一方,因此外鍵字段建在書表中 publish = models.ForeignKey(to='Publish') # to用來指代和哪張表有關係,默認關聯的就是主鍵字段 # 書與做者是多對多的關係, 外鍵字段建在任意一方均可以,建議建在查詢頻率較高的一方 author = models.ManyToManyField(to='Author') # django orm會自動幫你建立書和做者的第三張關係表 # author這個字段是一個虛擬字段 不能在表中展現出來,僅僅只是告訴orm,創建第三張表關係的做用 class Publish(models.Model): title = models.CharField(max_length=32) email = models.EmailField() class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() # 一對一的表關係,外鍵字段建在任意一方均可以,可是建議建在查詢頻率較高的一方 author_detail = models.OneToOneField(to='Author_detail') class Author_detail(models.Model): phone = models.BigIntegerField() addr = models.CharField(max_length=32)
注意點:django
- 一對多外鍵字段 建立的時候 ,同步到數據庫中,表字段會自動加
_id
後綴;若是本身加了_id
,會在後面再加一個_id
publish = models.ForeignKey(to='Publish')
默認關聯的是主鍵id,若是主鍵不是id,要本身關聯, 能夠加to_field=
於指定字段作關聯
django請求生命週期流程圖
url.py路由層
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'test/', views.test), url(r'testadd/', views.testadd) ]
若是url.py這樣寫,test
和testadd
後綴的訪問路徑,返回的內容是同樣的,緣由以下:後端
- url第一個參數是一個正則表達式
- 一旦正馬上結束則表達式可以匹配到內容,會馬上結束匹配關係,直接執行後面對應的函數
路由匹配
啓動django,在瀏覽器輸入127.0.0.1:8000/test
,django會自動加斜槓。瀏覽器
django匹配路由規律
不加斜槓(127.0.0.1:8000/test
),先匹配一次試試,若是匹配不上,會讓瀏覽器重定向,加一個斜槓(127.0.0.1:8000/test/
)再來一次匹配,若是還匹配不上,纔會報錯。app
取消django自動讓瀏覽器加斜槓的功能
在配置文件中settings.py中添加:
APPEND_SLASH = False # 該參數默認爲True
限制指定輸入的url
urlpatterns = [ url(r'^admin/', admin.site.urls), # url第一個參數是一個正則表達式 url(r'^test/$', views.test), # 一旦正馬上結束則表達式可以匹配到內容,會馬上結束匹配關係,直接執行後面對應的函數 url(r'^testadd/$', views.testadd) ]
這樣設置,只能輸入127.0.0.1:8000/test/
或127.0.0.1:8000/testadd/
注意:路由匹配只是匹配URL部分,不匹配get攜帶的參數 ?後面的參數
無名分組
正則表達式的無名分組
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/([0-9]{4})', views.test), # 表示test後面跟4個數字 url(r'^testadd/', views.testadd) ]
當你的路由中有分組的正則表達式,那麼在匹配到內容執行視圖函數的時候,會將分組內正則表達式匹配到的內容看成位置參數傳遞給視圖函數。
# 在視圖函數 def test(request, xxx): print('多餘的參數:', xxx) return HttpResponse('test view')
有名分組
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/(\d+)/', views.test), url(r'^testadd/(?P<year>\d+)/', views.testadd) # 正則表達式有名分組 ]
當你的路由中有分組而且給分組起了別名,那麼在匹配內容的時候,會將分組內的正則表達式匹配到的內容看成關鍵字參數傳遞給視圖函數
# 在視圖函數 def test(request, year): print('多餘的參數:', year) return HttpResponse('test view')
這樣就能夠利用有名和無名分組,咱們就能夠在調用視圖函數以前給函數傳遞額外的參數
注意:有名分組和無名分組不能混合使用,可是同一狀況下,無名分組可使用屢次,又名分組也可使用屢次
反向解析
舉個例子:
# urls.py urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/(\d+)/', views.test), url(r'^testadd/(?P<year>\d+)/', views.testadd), url(r'^index/', views.index), url(r'^home/', views.home), ] # views.py def index(request): return render(request, 'index.html') def home(request): return HttpResponse('home')
在上述代碼中,index.html
頁面中有不少跳轉的連接,都指向home
路由。若是像改變home
的url地址,那麼index.html
頁面中的不少跳轉home
的連接都有改變,有沒有動態綁定url地址的方法呢?反向解析就是。
定義
反向解析:根據一個別名,動態解析出一個結果,該結果能夠直接訪問對應的url
路由中沒有正則表達式,直接就是寫死的
url(r'^home/', views.home,name='xxx'), # 給路由與視圖函數對應關係起別名
前端反向解析
<p><a href="{% url 'xxx'%}">111</a></p>
後端反向解析
from django.shortcuts import render,HttpResponse,redirect,reverse def get_url(request): url = reverse('xxx') print(url) return HttpResponse('get_url')
無名分組的反向解析
在解析的時候,你須要手動指定正則匹配內容的是什麼
url(r'^home/(\d+)/', views.home, name='xxx'),
前端反向解析
<p><a href="{% url 'xxx' 12 %}">111</a></p>
後端反向解析
def get_url(request): url = reverse('xxx', args=(1,)) url2 = reverse('xxx', args=(1231,)) print(url) print(url2) return HttpResponse('get_url')
<font color='yellow'>手動傳入的參數 只須要知足 可以被正則表達式匹配便可</font>
有名分組的反向解析
url(r'^home/(?P<year>\d+)/', views.home, name='xxx'),
前端反向解析
能夠直接用無名分組的狀況
<p><a href="{% url 'xxx' 12 %}">111</a></p>
規範的寫法:
<p><a href="{% url 'xxx' year=121 %}">111</a></p>
後端反向解析
能夠直接用無名分組的狀況
也能夠規範寫:
def get_url(request): url = reverse('xxx', kwargs={'year': 13123}) print(url) return HttpResponse('get_url')
以編輯功能爲例,反向解析的應用
# urls.py url = (r'^edit_user/(\d+)/', views.edit_user, name='edit') # views.py def edit_user(request, edit_id): # edit_id就是用戶想要編輯數據主鍵值 pass
<!--頁面--> {% for user_obj in user_list %} <a href='/edit_user/{{user_obj.id}}/'>編輯</a> <a href='{% url 'edit' user_obj.id %}'>編輯</a> {% endfor %}
路由分發
前提:
在django中全部的app均可以有本身獨立的urls.py \ templates \ static. 正是因爲上面的特色 你用django開發項目就可以徹底作到多人分組開發 互相不干擾,每一個人只開發本身的app. 小組長只須要將全部人開發的app整合到一個空的django項目裏面, 而後在settings配置文件註冊 再利用路由分發將多個app整合到一塊兒便可完成大項目的拼接
路由分發解決的就是 項目的總路由 匹配關係過多的狀況,
使用路由分發, 會出現:
- 總路由再也不作匹配的活 而僅僅是作任務分發
- 請求來了以後 總路由不作對應關係,只詢問你要訪問哪一個app的功能 而後將請求轉發給對應的app去處理
使用:
總路由 (include)
只須要將全部的app的urls.py導入便可
from django.conf.urls import url, include from app01 import urls as app01_urls from app02 import urls as app02_urls urlpatterns = [ url(r'^app01/', include(app01_urls)), url(r'^app02/', include(app02_urls)), ] # 路由分發
子路由
# app01 urls.py from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^reg/', views.reg), ] # app02 urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^reg/', views.reg), ]
最省事的寫法:
# 連導入都不須要 url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls'))
名稱空間 (namespace)
當多個app中出現了起別名衝突的狀況 你在作路由分發的時候 能夠給每個app建立一個名稱空間 而後在反向解析的時候 能夠選擇到底去哪一個名稱空間中查找別名
在總路由中:
url(r'^app01/',include('app01.urls',namespace='app01')), url(r'^app02/',include('app02.urls',namespace='app02'))
前端:
<a href="{% url 'app01:reg' %}"></a> <a href="{% url 'app02:reg' %}"></a>
後端:
print(reverse('app01:reg')) print(reverse('app02:reg'))
可是也能夠不用,你只要 保證起別名的時候,在整個django項目中不衝突便可
僞靜態
就是將一個動態網頁假裝成一個靜態網頁,這樣能夠便於搜索引擎SEO(Search Engine Optimization),提升搜索引擎的收藏力度。
虛擬環境
-
每建立一個虛擬環境就相似於你從新下載了一個純淨python解釋器
-
以後該項目用到上面 你就裝什麼(虛擬環境一臺機器上能夠有N多個)
django版本區別
在urls.py
中路由匹配的方法有區別
django 1.xx版本
用的是url
from django.conf.urls import url urlpatterns = [ url(r'^reg.html',views.reg,name='app01_reg') ]
django 2.xx版本
用的是path
from django.urls import path urlpatterns = [ path('admin/', admin.site.urls), ]
- 這裏的path第一個參數不是正則,也不支持正則
- django2.X還有一個re_path的方法 該方法就是django1.X裏面url
- path提供了五種轉換器,可以將匹配到的數據自動轉換成對應的類型
- 還支持自定義的轉換器
django後端獲取文件對象
form表達傳文件須要注意的事項
- method必須改爲post
- enctype改成formdata格式
# urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^upload/', views.upload) ] # views.py def upload(request): if request.method == 'POST': print(request.FILES) # django會將文件類型的數據自動放入request.FILES file_obj = request.FILES.get('myfile') # 文件對象 # print(file_obj) # print(file_obj.name) with open(file_obj.name, 'wb') as f: for line in file_obj: f.write(line) return render(request, 'upload.html')