django orm中如何創建表關係
""" 表與表之間的關係: 一對多 多對多 一對一 沒有關係 判斷表關係的方法:換位思考 """ 圖書模型類(Book表) 出版社模型類(Publish表) 作者模型類(Author表) 作者詳情模型類(AuthorDetail表) """ 圖書和出版社是一對多的關係 外鍵字段建在多的那一方 book 圖書和作者是多對多的關係 需要創建第三張表來專門存儲 作者與作者詳情表是一對一 """
在項目中的models.py文件中創建表關係,前提是要將數據庫類型換成mysql:
from django.db import models # Create your models here. # 創建表關係 先將基表創建出來 然後再添加外鍵字段 # 圖書模型類(Book表) class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2) # 總共八位 小數點後面佔兩位 """ 圖書和出版社是一對多 並且書是多的一方 所以外鍵字段放在書表裏面 """ publish = models.ForeignKey(to='Publish') # 默認就是與出版社表的主鍵字段做外鍵關聯 """ 如果字段對應的是ForeignKey 那麼會orm會自動在字段的後面加_id """ """ 圖書和作者是多對多的關係 外鍵字段建在任意一方均可 但是推薦你建在查詢頻率較高的一方 """ authors = models.ManyToManyField(to='Author') """ authors是一個虛擬字段 主要是用來告訴orm 書籍表和作者表是多對多關係 讓orm自動幫你創建第三張關係表 """ # 出版社模型類(Publish表) class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) # 作者模型類(Author表) class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() """ 作者與作者詳情是一對一的關係 外鍵字段建在任意一方都可以 但是推薦你建在查詢頻率較高的表中 """ author_detail = models.OneToOneField(to='AuthorDetail') """ OneToOneField也會自動給字段加_id後綴 所以你也不要自作聰明的自己加_id """ # 作者詳情模型類(AuthorDetail表) class AuthorDetail(models.Model): phone = models.BigIntegerField() # 或者直接字符類型 addr = models.CharField(max_length=32) """ orm中如何定義三種關係 1、publish = models.ForeignKey(to='Publish') # 默認就是與出版社表的主鍵字段做外鍵關聯 2、authors = models.ManyToManyField(to='Author') 3、author_detail = models.OneToOneField(to='AuthorDetail') ForeignKey、OneToOneField(會自動在字段後面加_id後綴) """ # 在django1.X版本中外鍵默認都是級聯更新刪除的 # 多對多的表關係可以有好幾種創建方式 這裏暫且先介紹一種 # 針對外鍵字段裏面的其他參數 暫時不要考慮 如果感興趣自己可以百度試試看
django請求生命流程圖(重點)
這個圖是後期複習django最好的一個梳理方式
圖來自:https://www.cnblogs.com/guanxiying/p/12966067.html
路由層
路由匹配
url(r'test/',views.test), url(r'^$',views.testadd) """ url方法第一個參數是正則表達式 只要第一個參數正則表達式能夠匹配到內容 那麼就會立刻停止往下匹配 直接執行對應的視圖函數 在輸入url的時候會默認加斜槓 django內部幫你做到重定向 一次匹配不行 url後面加斜槓再來一次 """ # 取消自動加斜槓匹配 APPEND_SLASH = False/True # 默認是自動加斜槓的(True) urlpatterns = [ url(r'^admin/', admin.site.urls), # 首頁 url(r'^$',views.home), # 路由匹配 url(r'^test/$',views.test), url(r'^testadd/$',views.testadd), # 尾頁(瞭解) url(r'',views.error), ]
無名分組
""" 分組:就是給某一段正則表達式用小括號擴起來 """ url(r'^test/(\d+)/',views.test) def test(request,xx): print(xx) return HttpResponse('test') # 無名分組就是將括號內正則表達式匹配到的內容當作位置參數傳遞給後面的視圖函數
有名分組
""" 可以給正則表達式起一個別名 """ url(r'^testadd/(?P<year>\d+)',views.testadd) def testadd(request,year): print(year) return HttpResponse('testadd') # 有名分組就是將括號內正則表達式匹配到的內容當作關鍵字參數傳遞給後面的視圖函數
單個分組的多次使用
'''注意:無名分組與又名分組不能同時混合使用''' # 單個分組可以使用多次 url(r'^index/(\d+)/(\d+)/(\d+)/...', views.index), url(r'^index/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/...', views.index),
反向解析
# 通過一些方法得到一個結果 該結果可以直接訪問對應的url觸發視圖函數 # 先給路由與視圖函數起一個別名 url(r'^func_kkk/',views.func,name='ooo') # 反向解析 # 後端反向解析 from django.shortcuts import render,HttpResponse,redirect,reverse reverse('ooo') # 前端反向解析 <a href="{% url 'ooo' %}">111</a>
無名有名分組反向解析
無名分組反向解析
# 反向解析的本質:通過一些方法得到一個結果,該結果可以訪問到對應的url從而觸發視圖函數的運行 # 無名分組反向解析 # 路由層 url(r'index/(\d+)/', views.index,name='xxx') # 前端 # {% url 'xxx' %} 同樣會報相同的錯誤 {% url 'xxx' 123 %} # 後端 # reverse('xxx') 直接寫會報錯,必須要手動指定一個參數能夠被\d+匹配到 reverse('xxx', args=(1, ))
有名分組反向解析
# 有名分組反向解析 # 路由層 url(r'^func/(?P<year>\d+)/',views.func,name='ooo') # 前端 <a href="{% url 'ooo' year=123 %}">111</a> # 瞭解 <a href="{% url 'ooo' 123 %}">222</a> # 記憶 # 後端 # 正規寫法 瞭解 print(reverse('ooo',kwargs={'year':123})) # 簡便的寫法 記憶 print(reverse('ooo',args=(111,)))
數字代碼具體使用
# 數字一般情況下放的是數據的主鍵值 方便數據的編輯和刪除 url(r'^edit/(\d+)/',views.edit,name='xxx') def edit(request,edit_id): reverse('xxx',args=(edit_id,)) {%for user_obj in user_queryset%} <a href="{% url 'xxx' user_obj.id %}">編輯</a> {%endfor%}
路由分發
路由分發:能夠實現一個人寫一個功能應用,最後直接通過路由分發來將功能應用整合到一起,只需要訪問不同的url前綴就能夠訪問對應功能應用下的資源
django的每一個應用都可以有自己的templates文件夾、urls.py 、static文件夾 正是基於上述的特點 django能夠非常好的做到分組開發(每個人只寫自己的app)
''' 路由分發的優點: 1、一個人寫一個功能應用,整合時只需要將對應的app的路由加到總路由中即可(項目多人開發) 2、當一個django項目中url特別多的時候,爲了減輕總路由的壓力,便於維護,也可以使用路由分發 3、路由分發之後,總路由不再與視圖函數有直接對應關係,所有的資源訪問請求都轉交給對應的app來處理 ''' # 總路由 # 方式一: from django.conf.urls import url,include from django.contrib import admin from app01 import urls as app01_urls from app02 import urls as app02_urls urlpatterns = [ url(r'^admin/', admin.site.urls), # 路由分發 url(r'^app01/', include(app01_urls)), # 只要url前綴是app01開頭,全都交給app01處理 url(r'^app02/', include(app02_urls)), # 只要url前綴是app02開頭,全都交給app02處理 ] # 方式二: from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), '''注意:總路由的url千萬不要加$結尾'''(推薦使用) 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',namespace='app01')), url(r'^app02/', include('app02.urls',namespace='app02')), # 解析的時候 # app01 urlpatterns = [ url(r'^reg/',views.reg,name='reg') ] # app02 urlpatterns = [ url(r'^reg/',views.reg,name='reg') ] # 視圖函數使用:reverse('app01:reg')、reverse('app02:reg') # 前端頁面使用:{% url 'app01:reg' %}、{% url 'app02:reg' %} # 只要保證名字不衝突就沒有必要使用名稱空間 ''' 一般情況下,有多個app時在起別名時會加上app的前綴,這樣就能夠保證多個app之間名字不衝突 ''' # 子路由下: urlpatterns = [ url(r'^reg/',views.reg,name='app01_reg') ] urlpatterns = [ url(r'^reg/',views.reg,name='app02_reg') ] # 視圖函數直接使用別名即可
僞靜態(瞭解)
''' 靜態網頁:數據是寫死的 僞靜態:將一個動態網頁僞裝成靜態網頁 僞裝的目的:增大網站的seo查詢力度,增加了搜索引擎收藏網站的概率 搜索引擎本質上就是一個巨大的爬蟲程序 ''' urlpatterns = [ url(r'reg.html/', views.reg, name='app02_reg') ]
虛擬環境
''' 正常開發中,我們會給每個項目配備獨有的解釋器環境用來安裝只有該項目內使用的模塊,用不到的一概不裝 虛擬環境就是單獨的python解釋器環境,每創建一個虛擬環境就相當於重新下載了一個全新的python解釋器 擴展: 如何批量安裝模塊 開發當中我們會給每一個項目配備一個requirements.txt文件 裏面書寫了該項目所有的模塊即版本 只需要直接輸入一條命令即可一鍵安裝所有模塊即版本 '''
django版本區別
1、路由層使用方法 django1:url(),第一個參數支持正則 django2、django3:path(),第一個參數不支持正則,寫什麼就匹配什麼 re_path()支持正則,就類似django1的url() 2、django2、django3的path()提供了五種轉換器以及能夠自定義轉換器 3、級聯刪除更新 django1:默認自動級聯刪除更新 django2、django3:需要自己手動設置參數來實現級聯刪除更新 on_update=models.CASCADE on_delete=models.CASCADE
路由層的方法使用不同
# django1.X路由層使用的是url方法 url()第一個參數支持正則 # django2.X、3.X版本中路由層使用的是path方法 path()第一個參數是不支持正則的 寫什麼就匹配什麼 re_path()就等價於1.X中的url from django.urls import path, re_path from django.conf.urls import url re_path(r'^index/',index), url(r'^login/',login) # 2.X和3.X裏面的re_path就等價於1.X裏面的url
path內部的轉換器
雖然path不支持正則 但是它的內部支持五種轉換器 path('index/<int:id>/',index) # 將第二個路由裏面的內容先轉成整型然後以關鍵字的形式傳遞給後面的視圖函數 def index(request,id): print(id,type(id)) return HttpResponse('index') ''' str,匹配除了路徑分隔符(/)之外的非空字符串,這是默認的形式 int,匹配正整數,包含0。 slug,匹配字母、數字以及橫槓、下劃線組成的字符串。 uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。 path,匹配任何非空字符串,包含了路徑分隔符(/)(不能用?) '''
自定義轉換器
class MonthConverter: # 固定寫法 regex='\d{2}' # 屬性名必須爲regex def to_python(self, value): return int(value) def to_url(self, value): return value # 匹配的regex是兩個數字,返回的結果也必須是兩個數字 from django.urls import path,register_converter from app01.path_converts import MonthConverter # 先註冊轉換器 register_converter(MonthConverter,'mon') from app01 import views urlpatterns = [ path('articles/<int:year>/<mon:month>/<slug:other>/', views.article_detail, name='aaa'), ]
模型層中
1.X外鍵默認都是級聯更新刪除的
models.ForeignKey(to='Publish')
2.X和3.X中需要你自己手動配置參數
models.ForeignKey(to='Publish')
models.ForeignKey(to='Publish',on_delete=models.CASCADE...)