抽象基类 ( Abstract base classes)

抽象基类

当你想将一些共有信息放进其它一些model的时候,抽象化类是十分有用的。你编写完基类之后,在 Meta类中设置 abstract=True这个模型就不会被用来创建任何数据表。取而代之的是,当它被用来作为一个其他model的基类时,它的字段将被加入那些子类中。如果抽象基类和它的子类有相同的字段名,那么将会出现error(并且Django将抛出一个exception)。

一个例子:

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 模型将有三个项:name, agehome_groupCommonInfo 模型无法像一般的Django模型一样使用,因为它是一个抽象基类。它无法生成一张数据表或者拥有一个管理器,并且不能实例化或者直接储存。

许多应用场景下, 这种类型的模型继承恰好是你想要的。它提供一种在 Python 语言层级上提取公共信息的方式,同时在数据库层级上,每个子类各自仍然只创建一个数据库表。

 

第二个例子:

from django.contrib.auth.models import AbstractUser

class UserProfile(AbstractUser):
    nick_name = models.CharField(max_length=20, verbose_name=u"昵称", default=u"")
    birthday = models.DateField(verbose_name=u"生日", null=True, blank=True)
    gender = models.CharField(max_length=6, choices=(("male", u""), ("female", u"")), default="female")
    address = models.CharField(max_length=100, default=u"")
    mobile = models.CharField(max_length=11, null=True, blank=True)
    image = models.ImageField(upload_to="image/%Y/%m", default=u"image/default.png", max_length=100)

    class Meta:
        verbose_name = u"用户信息"
        verbose_name_plural = verbose_name

    def __str__(self):
    return self.username

UserProfile模型继承至 AbstractUser, 以此来扩展默认的User表。

 

不许“重写”字段

普通的 Python 类继承允许子类覆盖父类的任何属性。 但在 Django 中,重写 Field实例是不允许的(至少现在还不行)。如果基类中有一个 author字段,你就不能在子类中创建任何名为 author的字段。

重写父类的字段会导致很多麻烦,比如:初始化实例(指定在 Model.__init__ 中被实例化的字段) 和序列化。而普通的 Python 类继承机制并不能处理好这些特性。所以 Django 的继承机制被设计成与 Python 有所不同,这样做并不是随意而为的。

posted @ 2017-05-19 13:58  Vincen_shen  阅读(1109)  评论(0)    收藏  举报