美文网首页
模型继承

模型继承

作者: lkning | 来源:发表于2018-02-28 16:40 被阅读0次

django中的继承有三类;

  • 1.抽象继承
  • 2.多表继承
  • 3.proxy model(代理模型)

第一种情况

第1种情况表示你的父类仅仅是包含了多个子类的相同的字段,是为了重用,不会建表,我们只需要在抽象父类的Meta中设置abstract=True就行。比如:

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)  

这个时候,父类Meta中的abstract=True是不会传递给子类的,django会将子类的abstract设置为False

除了abstract之外,父类Meta中的db_table也不会继承给子类

在抽象类中使用关系(如外键,多对多关系,一对一关系)时候,肯定会设置related_name,但是子类继承抽象父类的时候,由于父类中的字段会继承给子类,则具有related_name的字段会被多个子类共享的。这样每一个子类的related_name就都一样了,其他模型通过related_name就不能找到正确的子类。

所以要正确设置related_namerelated_name中必须包含%(app_label)s%(class)s。如
%(app_label)s表示小写形式的,当前模型所在的,并且已经安装的app的名字%(class)s表示小写形式的,当前子类的类名字。

在common/models.py,有

class Base(models.Model):  
    m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related")  
  
    class Meta:  
        abstract = True  
  
class ChildA(Base):  
    pass  
  
class ChildB(Base):  
    pass  

在rare/models.py,有

from common.models import Base  
  
class ChildB(Base):  
    pass  

所以,上面的related_name就是 common_childa_relatedcommon_childb_related

第二种情况

第2中是多表继承,其中父类也是一个django模型,并且也会创建一个数据表,多表继承是django中隐式的一对一关系。例如:

class Place(models.Model):  
    name = models.CharField(max_length=50)  
    address = models.CharField(max_length=80)  
  
class Restaurant(Place):  
    serves_hot_dogs = models.BooleanField()  
    serves_pizza = models.BooleanField()  

其中虽然name和address存储在模型Place的表中,但是name和address对于Restaurant也是有效字段

>>> Place.objects.filter(name="Bob's Cafe")  
>>> Restaurant.objects.filter(name="Bob's Cafe")  

Restaurant和Place的关系,可以这么说:一个Restaurant一定是一个Place,而一个Place不一定是Restaurant

多表继承中,一般,父类的Meta属性不会继承到子类中,但是,ordering和 get_latest_by是继承的,如果子类不想继承父类的ordering的Meta,则可以手动显式的指定ordering=[]或者任何自己想要的值

多表继承的时候,是隐式的在父类和子类之间建立一个一对一关系,所以有时候,父类与其他类的关系会从父类下移到子类中。如果有多个子类,且子类不在关系中显式地指定related_name字段,django会引发验证错误

class Supplier(Place):  
    # Must specify related_name on all relations.  
    customers = models.ManyToManyField(Restaurant, related_name='provider')  

所以,继承父类,一旦子类中有关系,就加上related_name吧

django自动在子类和非抽象父类之间创建一个一对一关系,如果你想控制由子类连接回父类的属性的名字,你可以创建一个一对一关系,然后设置parent_link=True

class BaseOrder(models.Model):
  pass
class Gap(BaseOrder):
    baseorder = models.OneToOneField(BaseOrder, parent_link=True)

第三代理模型

在多表继承中,子类模型会创建一个数据表来存储不在父类模型中的额外字段,但是,如果我们只想改变某个模型的行为方法,而不是添加额外的字段,我们就可以使用

proxy model。代理model(proxy model)会继承父类的属性,并且只是添加一些对属性的操作的自定义方法而已。

class MyPerson(Person):  
    class Meta:  
        proxy = True  
  
    def do_something(self):  
        ...zh 

这里,MyPerson没有多创建数据表,MyPerson也是对Person的数据表进行操作,一般的,我们可以把MyPerson当做Person来使用,只是在do_something这个方法略有不同,比如

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

代理模型和原模型的区别如下面:

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

这里,OrderedPerson并不是创建了一个表,而是代理排序方法。也就是说,使用Person的检索方法并不会按last_name排序,而使用OrderedPerson检索出来的结果是按last_name排序的。OrderedPerson使用与Person类一样的检索方法。

OrderPerson返回的queryset自然是Person的,这是当然的。我们不能要求django返回OrderedPerson类的queryset,因为OrderedPerson只是代理而已,又不是真实的数据库表类。

注意的是,proxy model不能继承于抽象类,这是因为代理model是操作连接数据库的,也不能多重继承~因为你多重继承了,代理model就不知道去哪个父类找属性了

如果不指定代理model的manage,则代理model会自动继承父类的manage。我们也可以手动设置代理model的manage,这样,代理模型和父类模型的manage就分开了

为代理模型添加manage有两种方法:

一是直接在代理模型中直接指定manage

class NewManager(models.Manager):  
    ...  
  
class MyPerson(Person):  
    objects = NewManager()  
  
    class Meta:  
        proxy = True  

另外一种是当你不想覆盖父类模型中的manage但又想添加额外的manage,我们可以新建一个抽象模型,然后定义其manage,之后继承该抽象模型,如:

# Create an abstract class for the new manager.  
class ExtraManagers(models.Model):  
    secondary = NewManager()  
  
    class Meta:  
        abstract = True  
  
class MyPerson(Person, ExtraManagers):  
    class Meta:  
        proxy = True  

摘自这里

相关文章

  • JSon-Model

    字典转模型框架 Mantle所有模型都必须继承自MTModel JSONModel所有模型都必须继承自JSONMo...

  • 模型继承

    django中的继承有三类; 1.抽象继承 2.多表继承 3.proxy model(代理模型) 第一种情况 第1...

  • C++笔记五(面向对象编程下)

    十六 对象模型:关于vptr和vtbl 如图模型所示,B类继承A类,C类继承B类,子类有父类的成分,继承的包括数据...

  • 模型继承之多表继承

    这是django支持的第二种继承方式,使用这种方式,因为每个类都是一个完整的model,而不属于抽象基类,所以每个...

  • 模型基类常用方法

    模型基类 模型继承基类 最后控制器调用

  • Django之抽象基类

    Django中所有的模型都必须继承django.db.models.Model模型,不管是直接继承也好,还是间接继...

  • django 模型 继承

    今天遇到一个问题,有两张订单表,他们的使用很相似,都是用来采购某种物品,但是根据物品的分类不同,订单的内容又分为两...

  • Odoo10开发教程四(继承和Domain)

    继承 模型继承 Odoo提供两种继承机制,以模块化方式扩展现有模型。第一种继承机制允许一个模块修改另一个模块中定义...

  • iOS开发模型M和字典dic相互转换?

    一、Mode建立(demo下载) 模型.h文件(继承自NSObject) 模型.m文件 dic字典——>M模型se...

  • Swift-归档解档存储自定义类型数据

    模型内部操作外部存储、获取操作 1. 模型内部操作 1.1. 模型类必须继承NSObject 、NSCoding,...

网友评论

      本文标题:模型继承

      本文链接:https://www.haomeiwen.com/subject/bgkixftx.html