django

模型继承之多表继承2之代理继承

2018-08-24  本文已影响12人  陆_志东

在多表继承文章中,已经讲过,多表继承都是完整的model,都会创建数据库表,
那么可以不可以像抽象基类那样不让继承的子类创建数据表呢?方法就是代理继承

代理继承要做的就是:为原始模型创建一个代理 。你可以创建,删除,更新代理 model 的实例,而且所有的数据都可以像使用原始 model 一样被保存。 不同之处在于:你可以在代理 model 中改变默认的排序设置和默认的 manager ,更不会对原始 model 产生影响。
所以代理继承只是更改model在Python层的行为表现,比如:更改默认的 manager ,或是添加一个新方法。

使用了代理继承之后,原model和子model共用同一张数据表

例:假设你想给 Person 模型添加一个方法。你可以这样做:

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:
        proxy = True

    def do_something(self):
        # ...
        pass

特别的是,Person 的任何实例也可以通过 MyPerson访问,反之亦然:

>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")
<MyPerson: foobar>

你也可以使用代理 model 给 model 定义不同的默认排序设置。 你可能并不想每次都给Person模型排序,但是使用代理的时候总是按照last_name属性排序。这非常容易:

class OrderedPerson(Person):
    class Meta:
        ordering = ["last_name"]
        proxy = True

注意事项:

代理模型的管理器

如果你没有在代理 模型中定义任何管理器 ,代理模型就会从父类中继承管理器 。 如果你在代理模型中定义了一个管理器 ,它就会变成默认的管理器 ,不过定义在父类中的管理器仍然有效。
继续上面的例子,当你查询Person模型的时候,你可以改变默认 管理器,例如:

from django.db import models

class NewManager(models.Manager):
    # ...
    pass

class MyPerson(Person):
    objects = NewManager()  # 替换现有的管理器

    class Meta:
        proxy = True

如果你想要向代理中添加新的管理器,而不是替换现有的默认管理器,你可以创建一个含有新的管理器的基类,并继承时把他放在主基类的后面

# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
    secondary = NewManager()

    class Meta:
        abstract = True

class MyPerson(Person, ExtraManagers):  # 这样就会有两个管理器 objects 和  secondary 
    class Meta:
        proxy = True

多重继承

参考网址
尽量不要多重继承,因为Python的多重继承很容易出现问题,你应该尝试将你的继承关系保持得尽可能简洁和直接,这样你就不必费很大力气来弄清楚某段特定的信息来自哪里。

django不允许重写字段

如果基类中有一个 author字段,你就不能在子类中创建任何名为 author的字段。

上一篇下一篇

猜你喜欢

热点阅读