1.django中model跨文件的情況
在django中,在model中關(guān)聯(lián)一個(gè)其他app中的model也是可行的富雅。只要在文件的最上面導(dǎo)入model所在的文件即可。舉個(gè)簡單的例子:
from django.db import models
from geography.models import ZipCode
class Restaurant(models.Model):
# ...
zip_code = models.ForeignKey(
ZipCode,
on_delete=models.SET_NULL,
blank=True,
null=True,
)
2.字段名限制
- 1.不能是Python保留字
- 2.不能包含連續(xù)多于一個(gè)的下劃線。
3.model的屬性和方法
一個(gè)model非常重要的屬性是管理器。如果沒有自定義管理器顷链,默認(rèn)的名字為objects.
定義自定義方法在一個(gè)model上就是在你的類上加入新的自定義功能。 然而管理器方法試圖做的是全表范圍的事情屈梁,model方法應(yīng)該在特定的model實(shí)例上執(zhí)行嗤练,舉例如下:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
elif self.birth_date < datetime.date(1965, 1, 1):
return "Baby boomer"
else:
return "Post-boomer"
def _get_full_name(self):
"Returns the person's full name."
return '%s %s' % (self.first_name, self.last_name)
full_name = property(_get_full_name)
你也可以覆蓋預(yù)定義的model方法
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()
super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
do_something_else()
別忘了調(diào)用超級(jí)類方法至關(guān)重要。
4.model繼承
django中有三種類型的繼承
- 通常在讶,你只希望用父類來保持信息不至于在每個(gè)子類中都復(fù)制一遍液斜。該類不是孤立的使用翔横,所以抽象基類就是我們接下來要說的围橡。
- 如果你想繼承一個(gè)已經(jīng)存在的類熬芜,并希望每個(gè)類都有它自己的數(shù)據(jù)庫表 Multi-table inheritance 可以實(shí)現(xiàn)。
- 最后遮婶,如果你只想修改父類中的行為并不修改字段蝗碎,你可以使用Proxy models.
5.抽象基類
抽象基類在你想要把一些基礎(chǔ)信息放在其他多個(gè)model時(shí)就顯得非常重要了。 你可以先自己的基類并把put abstract=True 放在 Meta class中. 該類就不會(huì)再創(chuàng)建數(shù)據(jù)庫表了旗扑。取而代之蹦骑,當(dāng)該類應(yīng)用到其他model時(shí),該類的字段就會(huì)被加到其他子類中臀防。所以不能在子類中出現(xiàn)和基類字段相同的名字的字段眠菇,不然就會(huì)報(bào)錯(cuò)。舉例:
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
student將會(huì)有三個(gè)字段袱衷,CommonInfo model不能當(dāng)做一個(gè)正常的django model來用捎废,因?yàn)樗且粋€(gè)抽象類,它不會(huì)產(chǎn)生一個(gè)數(shù)據(jù)庫表也沒有一個(gè)管理器致燥,不能實(shí)例化不能被直接保存登疗。
Meta類繼承
當(dāng)一個(gè)抽象基類創(chuàng)建后,django創(chuàng)建Meta內(nèi)部類作為一個(gè)屬性嫌蚤。如果子類在內(nèi)部沒有描述一個(gè)Meta 類他將繼承父類的Meta.如果子類想要擴(kuò)展父類的Meta類辐益,可以繼承它,例如:
from django.db import models
class CommonInfo(models.Model):
# ...
class Meta:
abstract = True
ordering = ['name']
class Student(CommonInfo):
# ...
class Meta(CommonInfo.Meta):
db_table = 'student_info'
對(duì)于抽象基類的Meta類Django 做了一個(gè)調(diào)整:在安裝Meta屬性之前脱吱,先設(shè)置 sets abstract=False. 這意味著抽象基類的子類不會(huì)自動(dòng)變成抽象類.如果你想要子類依然是一個(gè)基類智政,記得加上 abstract=True .在抽象基類的Meta類中一些屬性沒有什么意義。比如箱蝠,db_table,因?yàn)椴豢赡芩械淖宇惗加幸粯拥拿帧?/p>
6.related_name 和 related_query_name
當(dāng)你在 ForeignKey or ManyToManyField上使用一個(gè)related_name or
related_query_name , 你必須指定一個(gè)唯一的反向名和查詢名在那個(gè)字段上续捂。在抽象基類上這樣就會(huì)導(dǎo)致一些問題垦垂。因?yàn)樵擃惿系淖侄螘?huì)被包含在子類中,這樣每次查詢屬性的值都是一樣的值牙瓢。
為了解決這個(gè)問題劫拗。當(dāng)你在抽象基類中使用related_name or related_query_name , 值應(yīng)該包含’%(app_label)s’ and ’%(class)s’.
- ’%(class)s’ 被子類中字段名的小寫形式代替。
- ’%(app_label)s’被子類所處的app名的小寫形式代替一罩。
舉例:
common/models.py:
from django.db import models
class Base(models.Model):
m2m = models.ManyToManyField(
OtherModel,
related_name="%(app_label)s_%(class)s_related",
related_query_name="%(app_label)s_%(class)ss",
)
class Meta:
abstract = True
class ChildA(Base):
pass
class ChildB(Base):
pass
rare/models.py:
from common.models import Base
class ChildB(Base):
pass
common.ChildA.m2m field 的逆向的名稱為 common_childa_related杨幼,逆向的查詢名為common_childas. rare.ChildB.m2m field 的逆向的名稱為 rare_childb_related, 逆向的查詢名為
rare_childbs.如果你不指定 related_name 屬性在abstract base class中, 默認(rèn)的逆向名稱為
類名稱后加_set字符串聂渊。例如,在上面的例子中, 如果 related_name attribute 省略, m2m field 逆向名稱為childa_set in the ChildA case and childb_set for the ChildB field