- model是Django中的數據模型
- 每個model都是繼承自django.db.models.Model的子類
- 每個model都映射一個數據表
- model中的每個類屬性對應著數據表中的一列
- django支持ORM
- 創建model并進行migrate后
- Django會自動生成表名(可以自定義)
- Django會自動增加主鍵一列(可以自定義)
- Django會根據不同數據庫創建不同的SQL語句
-
Field中的常見選項
- null:允許該列數據為空(默認為False)
- blank:主要用于是否允許表單為空(默認為False)
- choices:為一個Field提供可選項(并且默認生成的表單為一個選項)
from django.db import models class Person(models.Model): # choices的對象是一個可迭代對象,其元素為‘含有兩個元素的元組’ SHIRT_SIZES = ( ('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), ) name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES) # choice API >>> p = Person(name="Fred Flintstone", shirt_size="L") >>> p.save() >>> p.shirt_size 'L' >>> p.get_shirt_size_display() # get_FOO_display()方法可以顯示具體內容 'Large'
- default:既可以是一個數值對象,也可以是一個可調用對象
- help_text:在生成的表單中展示‘幫助’信息
- primary_key:將某一列設置為主鍵(該列變為只讀);默認為False,即Django會自動創建一個整型主鍵
- unique:該列中的每個數據必須獨一無二(默認為False)
- 自動生成主鍵
默認情況下,如果不顯式指定主鍵,Django會在model中自動添加以下屬性id = models.AutoField(primary_key=True)
- 顯式指定列名
對于非關系型列(即非ForeignKeyField,ManyToManyField,OneToOneField),第一個位置參數為空時,將默認屬性名為列名;否則使用位置參數作為列名
對于關系型列,需要指定位置參數以表明關聯的數據表# 列名為"person's first name" first_name = models.CharField("person's first name", max_length=30) # 列名為"first_name" first_name = models.CharField(max_length=30) # 關聯表為"Poll" poll = models.ForeignKey( Poll, on_delete=models.CASCADE, verbose_name="the related poll", )
- 關聯
- Many-to-one 關聯
使用django.db.models.ForeignKey,第一個位置參數需要指定關聯表名 - Many-to-many 關聯
使用django.db.models.ManyToManyField(相關的兩個表中,只需要在一個表中指定即可)
可以顯式的創建many-to-many的關聯數據表from django.db import models class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): # __unicode__ on Python 2 return self.name class Group(models.Model): name = models.CharField(max_length=128) # 通過through指定關聯表 members = models.ManyToManyField(Person, through='Membership') def __str__(self): # __unicode__ on Python 2 return self.name class Membership(models.Model): person = models.ForeignKey(Person, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE) date_joined = models.DateField() invite_reason = models.CharField(max_length=64)
- One-to-one 關聯
使用django.db.models.OneToOneField,可以用于擴展某一model
- Many-to-one 關聯
-
Meta 選項
Model的Meta中保存著所有非列的屬性(比如ordering(默認排序)、db_table(數據表名稱)等等)from django.db import models class Ox(models.Model): horn_length = models.IntegerField() # class Meta 是可選項 class Meta: ordering = ["horn_length"] verbose_name_plural = "oxen"
- Model 的方法
我們可以在Model中自定義方法,也可以使用或者重載Model中已有的方法
有兩個方法在大多數情況下需要我們自己定義- __ str__()
- get_absolute_url()
該方法告訴Django如何得到一個對象的URL(一般使用django的reverse()函數)def get_absolute_url(self): from django.urls import reverse return reverse('people.views.details', args=[str(self.id)])
from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def save(self, *args, **kwargs): do_something() # 關鍵在于對Model.save()方法的繼承上,另外通過使用(*args, **kwargs)參數可以自動獲取相關參數 super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. do_something_else()
- Model的繼承
django中存在三種繼承- Abstract base classes
- Multitable inheritance
- Proxy models
- Abstract base classes
在class Meta中設置abstract = True,就可以將該model變為抽象類——該類中定義的列屬性可以被子類所繼承而無需重新定義,且class Meta中的屬性亦會被繼承(除了abstract = True)
Abstract base classes并不會產生數據表,也不能直接用于創建實例
為了指定子類關聯表列的relate_name,可以在abc類的關聯表列中進行設置from django.db import models class CommonInfo(models.Model): name = models.CharField(max_length=100) age = models.PositiveIntegerField() # 將CommonInfo聲明為一個abc類 class Meta: abstract = True ordering = ['name'] class Student(CommonInfo): # Student 類自動繼承name和age列 home_group = models.CharField(max_length=5) class Meta: # Student 類會繼承CommonInfo中的Meta的信息 # 不過在此之前會自動設置abstract=False(當然也可以自己顯式地設置abstract=True從而成為abc類) db_table = 'student_info'
# common/models.py from django.db import models class Base(models.Model): m2m = models.ManyToManyField( OtherModel, # 若不設置related_name,則默認為"子類名 + '_set'" # %(app_label)s 指代當前應用名稱 # %(class)s 指代當前類的類名 related_name="%(app_label)s_%(class)s_related", related_query_name="%(app_label)s_%(class)ss", ) class Meta: abstract = True # OtherModel 使用 ChildA 類時的屬性名將是'common_childa_related' class ChildA(Base): pass class ChildB(Base): pass
- Multi-table inheritance
父類和子類都可以生成數據表,且子類會繼承父類的類屬性(列屬性),但父類和子類是兩個不同的表
此外,不同于abc類,子類不會繼承父類class Meta中的屬性 - Proxy models
Proxy model用于當你只想為一個表增加一些方法或者Meta屬性,而不想改變原model的代碼時from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) class MyPerson(Person): class Meta: # 指定該類為Person的代理數據模型 proxy = True # 在該proxy model中可以增加一個額外的Meta屬性 odering = ['last_name'] # 在該proxy model中可以增加一些額外的方法 def do_something(self): # ... pass # 需要注意的一點是Person和MyPerson類都可以調用Person數據表中的數據 # 不同之處在于通過Person類創建/查找到的實例中沒有ordering屬性,也不能調用do_something方法