第三篇:Django建立表關係及部分講解
阿新 • • 發佈:2021-06-26
第三篇:Django建立表關係及部分講解
目錄一、Django中orm建立表關係
一、資料庫中的表關係
我們可以通過換位思考來理解資料表之間的關係,表關係如下所示。
"""
表與表之間的關係
一對多
多對多
一對一
沒有關係
判斷表關係的方法:換位思考
"""
我們先簡單建立幾張表,然後判斷各個表之間的關係。
分別為圖書表、作者表、出版社表、作者詳情表【未畫出】。我們逐個分析個表之間的關係,我們發現。
圖書和出版社是一對多的關係 外來鍵欄位建在多的那一方 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') # 預設就是與出版社表的主鍵欄位做外來鍵關聯 # 外來鍵:【多對多】圖書和作者是多對多的關係 外來鍵欄位建在任意一方均可 但是推薦你建在查詢頻率較高的一方 authors = models.ManyToManyField(to='Author') """ 注意:authors是一個虛擬欄位 主要是用來告訴orm 書籍表和作者表是多對多關係,讓orm自動幫你建立第三張關係表。 """
注意:
""" 1、如果欄位對應的是ForeignKey那麼會orm會自動在欄位的後面加_id 2、如果你自作聰明的加了_id那麼orm還是會在後面繼續加_id """ 所以,後面在定義ForeignKey的時候就不要自己加_id
-
出版社表
class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32)
-
作者表
class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() # 外來鍵:【一對一】作者與作者詳情是一對一的關係 外來鍵欄位建在任意一方都可以 但是推薦你建在查詢頻率較高的表中 detail = models.OneToOneField(to='AuthorDetail') """ OneToOneField也會自動給欄位加_id字尾,所以你也不要自作聰明的自己加_id """
-
作者詳情表
class AuthorDetail(models.Model): # 注意BigIntegerField phone = models.BigIntegerField() # 或者直接字元型別 addr = models.CharField(max_length=32)
-
建立效果如下
我們進一步分析,開啟app01_book,我們發現自動建立了主鍵欄位id,同時給關聯外來鍵的欄位publish自動添加了字尾,變成了publish_id。【此關係為多對一】
開啟app01_author,我們發現給detail添加了字尾,變成了detail_id。【此關係為一對一】
開啟app01_book_author,我們發現也自動添加了字尾。【此關係為多對多】
總結:
"""orm中如何定義三種關係?"""
# 預設就是與出版社表的主鍵欄位做外來鍵關聯
publish = models.ForeignKey(to='Publish')
# 預設就是id之間建立外來鍵關係
authors = models.ManyToManyField(to='Author')
# 預設就是id之間建立外來鍵關係
author_detail = models.OneToOneField(to='AuthorDetail')
"""ForeignKey、OneToOneField、ManyToManyField會自動在欄位後面加_id字尾"""
補充:
# 在django1.X版本中外來鍵預設都是級聯更新刪除的
# 多對多的表關係可以有好幾種建立方式 這裡僅為其中一種
# 針對外來鍵欄位裡面的其他引數 暫時不要考慮
二、Django請求生命週期流程圖
補充:
快取資料庫:提前已經將你想要的資料準備好了 你來直接拿就可以,提高效率和響應時間。
案例:當你在修改你的資料的時候 你會發現資料並不是立刻修改完成的而是需要經過一段時間才會修改【部落格園】
三、Django分佈講解
一、路由層(urls.py)
1、路由匹配
為了測試路由,我們先設定這樣的路由路徑。
"""urls.py"""
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'test/', views.test),
url(r'testadd/', views.testadd)
]
"""views.py"""
def test(request):
return HttpResponse('date from test')
def testadd(request):
return HttpResponse('date from testadd')
從瀏覽器中訪問127.0.0.1:8000/test
,得到以下效果。
看著很正確,但是我們又訪問127.0.0.1:8000/testadd
,我們會發現出現了錯誤,仍然得到了以前的頁面。
原因如下:
url方法第一個引數是正則表示式,只要第一個引數正則表示式能夠匹配到內容那麼就會立刻停止往下匹配,直接執行對應的檢視函式。
你在輸入url的時候會預設加斜槓,django內部幫你做到重定向,一次匹配不行,url後面加斜槓再來一次。
總結:
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 首頁【^以...開頭,$以...結尾】
url(r'^$',views.home),
# 路由匹配
url(r'^test/$',views.test),
url(r'^testadd/$',views.testadd),
# 尾頁(瞭解,不完善,有小bug)
url(r'',views.error),
]
補充:
# 取消自動加斜槓
APPEND_SLASH = False/True # 預設是自動加斜槓的
2、無名分組
分組:就是給某一段正則表示式用小括號擴起來
無名分組就是將括號內正則表示式匹配到的內容當作位置引數傳遞給後面的檢視函式。
url(r'^test/(\d+)/',views.test) # \d匹配數字 +匹配一個或多個
def test(request,xx):
print(xx) # 使用xx作為形參,可以得到(\d+)匹配到的數字
return HttpResponse('test')
3、有名分組
可以給正則表示式起一個別名
有名分組就是將括號內正則表示式匹配到的內容當作關鍵字引數傳遞給後面的檢視函式。
url(r'^testadd/(?P<year>\d+)',views.testadd) # (?P<year>\d+)
def testadd(request,year):
print(year) # 關鍵字實參year,必須是year
return HttpResponse('testadd')
4、無名分組和有名分組是否可以混用?
不能混用,但是同一個分組可以使用N多次
url(r'^index/(\d+)/(\d+)/(\d+)/',views.index),
def index(request, x, y, z): # 位置形參
pass
url(r'^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/',views.index),
def index(request, year, age, month) # 關鍵字引數傳參
5、反向解析
# 我們可以給路由與檢視函式起一個別名
url(r'^func/',views.func,name='ooo')
# 訪問方式如下即可
# 前端反向解析
<a href="{% url 'ooo' %}">111</a> # a連結訪問的路徑為urls.py下 路由關係名為'ooo'的路徑
# 後端方向解析
"""urls.py"""
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^func/', views.func, name='ooo')
]
"""views.py"""
def func(request):
print(reverse('ooo')) # /func/
return HttpResponse('date from func')
訪問127.0.0.1:8000/func/
服務端效果如下。