Django中model的一些細(xì)節(jié)問題總結(jié)

1.django中model跨文件的情況

在django中,在model中關(guān)聯(lián)一個(gè)其他app中的model也是可行的。只要在文件的最上面導(dǎo)入model所在的文件即可。舉個(gè)簡(jiǎn)單的例子:

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ù)庫(kù)表 Multi-table inheritance 可以實(shí)現(xiàn)。
  • 最后,如果你只想修改父類中的行為并不修改字段,你可以使用Proxy models.

5.抽象基類

抽象基類在你想要把一些基礎(chǔ)信息放在其他多個(gè)model時(shí)就顯得非常重要了。 你可以先自己的基類并把put abstract=True 放在 Meta class中. 該類就不會(huì)再創(chuàng)建數(shù)據(jù)庫(kù)表了。取而代之,當(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ù)庫(kù)表也沒有一個(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容