目錄html
換位思考,先粘在一張表上面分析, 而後再站在另外一張表上分析前端
外鍵字段建立在任意一張表均可以,簡易在查詢頻率較高的一方添加python
OneToOneField
正則表達式
models.OneToOneField(to='Author_detail') # fk + unique
外鍵字段建立在多的那一方django
ForeignKey
後端
models.ForeignKey(to='Publish') # to用來指代跟哪張表有關係 默認關聯的就是表的主鍵字段
外鍵關係須要建立第三張表來處理。瀏覽器
ManyToManyField
app
models.ManyToManyField(to='Author') # django orm會自動幫你建立第三張關係表
urlpatterns = [ url(r'^admin/', admin.site.urls), ]
url的第一個參數其實就是一個正則表達式,只要該正則表達式可以匹配到內容,就會馬上執行後面的視圖函數,再也不往下繼續匹配。函數
Django settings.py配置文件中默認沒有 APPEND_SLASH 這個參數,但 Django 默認這個參數爲 APPEND_SLASH = True。 其做用就是自動在網址結尾加'/'。post
咱們定義了urls.py:
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^blog/$', views.blog), ]
其效果就是:
訪問 http://www.example.com/blog 時,默認將網址自動轉換爲 http://www.example/com/blog/ 。
若是在settings.py中設置了 APPEND_SLASH=False,此時咱們再請求 http://www.example.com/blog 時就會提示找不到頁面。
Django 路由匹配的規律:
?
後面攜帶的參數將分組內正則表達式匹配到的內容當作位置參數傳遞給視圖函數
url(r'^test/([0-9]{4})/', views.test) 訪問的url:http://127.0.0.1/test/1111 # 當你的路由中有分組的正則表達式 那麼在匹配到內容 # 執行視圖函數的時候 會將分組內正則表達式匹配到的內容當作位置參數傳遞給視圖函數 def test(request,xxx): ''' 此時url有第二個參數,會傳遞給視圖函數位置參數傳進來。 若是不寫接收的位置參數則會報錯 test() takes 1 positional argument but 2 were given ''' print(xxx) # 1111 pass
將分組內正則表達式匹配到的內容當作關鍵字參數傳遞給視圖函數
url(r'^test/(?P<year>[0-9]{4})/', views.test) 訪問的url:http://127.0.0.1/test/1111 # 當你的路由中有分組的正則表達式 那麼在匹配到內容 # 執行視圖函數的時候 會將分組內正則表達式匹配到的內容當作關鍵字參數傳遞給視圖函數 def test(request,year): ''' 此時url有第二個參數,會傳遞給視圖函數關鍵字參數傳進來。 若是不寫接收的關鍵字參數則會報錯 testadd() got an unexpected keyword argument 'year' ''' print(year) # 1111 pass
利用有名個無名分組 咱們就能夠在調用視圖函數以前給函數傳遞額外的參數
注意:無名分組和有名分組不能混合使用
可是同一種分組的狀況下 可使用屢次,
無名能夠有多個
有名能夠有多個
給路由匹配設置一個別名,
根據這個別名,動態解析出一個結果,該結果能夠直接訪問對應的url。
urls.py: url(r'^home/',views.home,name='hm'), url(r'^index/$',views.index), views.py: def home(request): return HttpResponse(reverse('hm')) def index(request): print(reverse('hm')) # /home/ return render(request,'test.html') test.html: <body> <div>TEST</div> <p><a href="{% url 'hm' %}">點我點我</a></p> </body> 當咱們在瀏覽器URL輸入http://127.0.0.1:8000/index/的時候, python後端進行reverse反向解析成 別名爲'hm'的路徑前綴,也就是home路徑, 用test.html 頁面渲染,html也可使用反向解析 python後端使用反向解析: reverse('hm') 前端html使用反向解析: {% url 'hm' %} 將路徑解析爲/home/。
urls.py: url(r'^home/(\d+)/',views.home,name='hm'), url(r'^index/',views.index), views.py: def home(request,xxx): # 使用無名分組,視圖函數必須寫位置參數 print(xxx) return HttpResponse('ok') def index(request): print(reverse('hm',args=(1,))) # 無名分組須要手動給別名傳遞一個參數才能匹配上,這個參數會傳遞到視圖函數當作位置參數。 return render(request,'test.html') test.html: <body> <div>TEST</div> <p><a href="{% url 'hm' 1 %}">點我點我</a></p> </body> 當一個無名分組使用別名的時候,在瀏覽器URL輸入http://127.0.0.1:8000/index/,python後端進行reverse反向解析成 別名爲'hm'的路徑前綴,也就是home路徑,須要手動給解析出來的路徑加參數,否則匹配不成功 用test.html 頁面渲染,而且html使用反向解析,也須要手動傳入參數 python後端使用反向解析: reverse('hm',args=(1,)) 前端html使用反向解析: {% url 'hm' 1 %} 將路徑解析爲/home/1。
urls.py: url(r'^home/(?P<year>\d+)/',views.home,name='hm'), url(r'^index/',views.index), views.py: def home(request,year): # 使用有名分組,視圖函數必須寫關鍵字參數 print(year) return HttpResponse('ok') def index(request): print(reverse('hm',args=(1,))) # 這樣也能夠,但不正規 print(reverse('hm',kwargs={"year":1})) # 最正規的寫法,由於有名分組傳入的是關鍵字參數,用kwargs參數來表示 return render(request,'test.html') test.html: <body> <div>TEST</div> <p><a href="{% url 'hm' 1 %}">點我點我</a></p> # 這樣也能夠,但不正規 <p><a href="{% url 'hm' year=1 %}">點我點我</a></p> # 最正規的寫法,由於有名分組傳入的是關鍵字參數 </body> 當一個無名分組使用別名的時候,在瀏覽器URL輸入http://127.0.0.1:8000/index/,python後端進行reverse反向解析成 別名爲'hm'的路徑前綴,也就是home路徑,須要手動給解析出來的路徑加參數,否則匹配不成功。 用test.html 頁面渲染,而且html使用反向解析,也須要手動傳入參數 python後端使用反向解析: reverse('hm',kwargs={"year":1}) 前端html使用反向解析: {% url 'hm' year=1 %} 將路徑解析爲/home/1。
僞代碼以編輯用戶信息爲例,演示具體用法:
urls.py: url(r'^edit_user/(\d+)',views.edit_user,name='edit'), views.py: def edit_user(request,edit_id): # 查出來全部 user_list # edit_id 就是用戶想要編輯數據的主鍵值 print(edit_id) return render(request,'edit_user.html',{"user_list":user_list}) edit_user.hmtl: {% 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整合到一個空的django項目裏面,在settings配置文件裏註冊就能夠了。
路由分發解決的就是項目的總路由匹配關係過多的狀況,使用路由分發 會將總路由再也不作匹配的活 而僅僅是作任務分發
咱們新建一個app02,如今個人目錄結構是:
python3 manage.py startapp app02
好了以後
咱們在app01目錄中建立urs.py app01/urls.py: from app01 import views from django.conf.urls import url urlpatterns = [ url(r'^reg/',views.reg), ] app01/views.py: def reg(request): return HttpResponse("app01 reg") ----------------------------------- app02/urls.py: from app02 import views from django.conf.urls import url urlpatterns = [ url(r'^reg/',views.reg), ] app02/views.py: def reg(request): return HttpResponse("app02 reg") 總urls:mysite/urls.py: 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)), ] 或者更省事的寫法,不用把兩個app的urls.py導過來: urlpatterns = [ url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')), ] 最終效果,在瀏覽器url中輸入 http://127.0.0.1:8000/app01/reg # app01 reg http://127.0.0.1:8000/app02/reg # app02 reg
當多個app中出現了起別名衝突的狀況 你在作路由分發的時候 能夠給每個app建立一個名稱空間,而後在反向解析的時候 能夠選擇到底去哪一個名稱空間中查找別名
url(r'^app01/',include('app01.urls',namespace='app01')), url(r'^app02/',include('app02.urls',namespace='app02')) # 後端 print(reverse('app01:reg')) print(reverse('app02:reg')) # 前端 <a href="{% url 'app01:reg' %}"></a> <a href="{% url 'app02:reg' %}"></a> 其實不用這麼麻煩, 參考建議 起別名的時候統一加上應用名前綴,這樣你的別名就不會重複了。 urlpatterns = [url(r'^reg/',views.reg,name='app01_reg')] urlpatterns = [url(r'^reg/',views.reg,name='app02_reg')]
將一個動態網頁假裝成一個靜態的網頁,來提升搜索引擎SEO的查詢頻率,提升網站的曝光度!
怎麼作呢,好比博客園是一個動態網站,可是看起來像一個靜態網站,是由於每篇文章都有後綴名.html
那麼咱們也能夠寫,在路由匹配規則中寫上
# https://www.cnblogs.com/qinyujie/p/11394671.html url(r'^article/(\d+).html',views.article)
虛擬環境就至關於從新下載了一個純淨的python解釋器,以後項目用這個虛擬環境,你須要什麼就安裝什麼,與系統環境上存在的軟件不衝突。
urls.py路由匹配的方法有區別。
導入的模塊是
from django.conf.urls import url
,
urlpatterns 中 url 對應的是正則表達式,
以下:
from django.conf.urls import url urlpatterns = [ url = ('test',view.test) ]
導入的模塊是from django.urls import re_path,path
path中第一個參數不支持正則表達式,寫了什麼就只能匹配什麼,匹配不到就報錯。
django 2.X 以爲你習慣了以前的正則表達式來匹配,特別人性化 ,
提供一個re_path
方法,這個方法就是1.X版本中的url()
以下:
from django.urls import path,re_path urlpatterns = [ path = ('test',view.test), re_path = (r'^test/(\d+)',view.test) ]
django 2.X的版本中還提供了五種轉換器,
urlpatterns = [ path = ('test/<str:\d+>',view.test) path = ('test/<int:\d+>',view.test) path = ('test/<slug:\d+>',view.test) path = ('test/<uuid:\d+>',view.test) path = ('test/<path:\d+>',view.test) ]
除了內置的五種轉換器外,還能夠自定義本身的轉換器。
class CVT185Phone: regex = '185\d{8}' def to_python(self, value): return int(value) def to_url(self, value): return '%11d' % value from django.urls import register_converter from app.converter import CVT185phone register_converter(CVT185phone,'phone185') path('page/<phone185:msg>/',views.page,name="pages")
經過路由分發,使用app01上傳文件的功能上傳一個文件;
mysite/urls.py urlpatterns = [ url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')), ] app01/urls.py from app01 import views from django.conf.urls import url urlpatterns = [ url(r'^upload/',views.upload,name='app01_upload'), ] app01/views.py from django.shortcuts import reverse,render,HttpResponse,redirect def upload(request): if request.method == "POST": print(request.FILES) file_obj = request.FILES.get("myfile") with open(file_obj.name,"wb") as f: for i in file_obj: f.write(i) return render(request,'upload.html') templates/upload.html <body> <form action="" method="post" enctype="multipart/form-data"> 請選擇文件 <input type="file" name="myfile"> <input type="submit" class="btn btn-primary">提交 </form>