美文网首页
Model inheritance 模型继承

Model inheritance 模型继承

作者: 低吟浅唱1990 | 来源:发表于2017-06-11 19:21 被阅读159次

    Django中模型的继承与Python普通类的继承一样,不过基类要是django.db.models.Model
    在Django中有三种继承的方式

    • 仅仅想用父类保存一下不是每个子类都键入的信息,抽象class是很好的选择
    • 继承一个存在model,并且想让每个model都有一个数据表。多表继承
    • 改变在Python层面上的一些model的行为,而不是model的字段。

    Abstract base classes

    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)
    >>>abstract=True表明CommonInfo是一个抽象类,不在数据库中建表,CommonInfo不能直接使用。同时Student与CommonInfo不能有名称相同的属性。Student由于继承了CommonInfo,所有Student有三个字段name,age,home_group。如果子类中没有定义Meta则其继承父类的Meta。子类也可以扩展父类的Meta
    
     class Meta(CommonInfo.Meta): db_table = 'student_info'
    

    小心处理related_name and related_query_name
    如果使用related_name和related_query_name使用在外键和多对多的关系中,必须制定一个唯一的名字。在抽象类中使用related_name和related_query_name需要与app_label和class标记
    '%(class)s'将会被子类小写名,而'%(app_label)s'会被子类所在的app小写名替代

    common/models.py

    from django.db import models
    class Base(models.Model):
          m2m = models.ManyToManyField(OtherModel,
    relate_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
    >>>
    common.ChildA.m2m的reverse name是common_childa_related
    reverse query name是common_childas。如果不指定related_name则默认为子类名+_set, ------>childa_set
    

    Multi-table inheritance

    from django.db import models
    class Place(models.Model):
          name = models.CharField(max_lenght=50)
          address = models.CharField(max_length=80)
    class Restaurant(Place):
          serves_hot_dogs = models.BooleanField(default=False)
          serves_pizza = models.BooleanField(default=False)
          place_ptr = models.OneToOneField( 
              Place,  
              on_delete=models.CASCADE, 
              parent_link=True,
        ) #与父类进行一对一关联
    >>>
    这种写法会在数据库中创建两个表,同时Restaurant拥有Place所有的字段
    
    >>> Place.objects.filter(name="Bob's Cafe")
    >>> Restaurant.objects.filter(name="Bob's Cafe")
    >>> p = Place.objects.get(id=12)
    # If p is a Restaurant object, this will give the child class: >>> p.restaurant
    <Restaurant: ...>
    

    Proxy models

    采用Multi-table inheritance的方式需要为每一个类创建一个数据表,比较耗资源。可以采用代理模型,可以对代理模型进行数据操作,而反应在原始模型上

    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
    
    >>> MyPerson和Person会操作同一个数据表
    >>> p = Person.objects.create(first_name="foobar")
    >>> MyPerson.objects.get(first_name="foobar") 
    <MyPerson: foobar>
    

    proxy model必须继承一个非抽象model,proxy model还可以继承一个proxy model共享一个非抽象model。如果没有为proxy指定一个manager那么其将继承父类的manager,如果定义了一个manager,那么这个manger称谓proxy model的默认manager。同时父类的manager照样能够运行。

    相关文章

      网友评论

          本文标题:Model inheritance 模型继承

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