Django模型继承:使用现有的超类创建子类

mic*_*mit 23 django inheritance model

我正在使用多表继承,并想知道如何从超类的实例创建一个继承的类型.

使用文档中给出的示例:

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()
Run Code Online (Sandbox Code Playgroud)

现在当你创建一个Restaurant,你自动创建一个Place,这很好,以及我期望和想要的行为.

但是,如果我做了一个Place,后来决定我要转换为特定类型(如Restaurant).你如何Restaurant使用现有的创建Place

Mar*_*mro 27

多表继承只是OneToOneFieldPlace和Restaurant之间的关系.

place = Place.objects.get(id=1)               

# Create a restaurant using existing Place   
restaurant = Resturant(place_ptr=place)
restaurant.save()
Run Code Online (Sandbox Code Playgroud)

  • 你应该添加restaurant .__ dict __.update(place .__ dict__),参见[Daniel Roseman的回答](http://stackoverflow.com/questions/4064808/django-model-inheritance-create-sub-instance-of-existing-instance -沮丧). (10认同)
  • 这将导致restaurant.name被清空.因为restaurant.save()将使用name =''(因为restaurant = Resturant())更新Place ...必须有更好的方法...... (9认同)

小智 10

place = Place.objects.get(id=1)

# Create a restaurant using existing Place
place.__class__ = Restaurant
place.save()
restaurant = place
Run Code Online (Sandbox Code Playgroud)


vel*_*lis 9

虽然没有记录,但这似乎可以解决问题:

restaurant(place_ptr=place).save_base(raw=True)
Run Code Online (Sandbox Code Playgroud)

这无需使用任何 hack 即可解决问题,并且是最短的解决方案,在处理方面也是如此,使用 Django API。

在搜索此解决方案时,我还发现了一个稍长的解决方案,但使用了记录的 API。它与Mariusz 的答案基本相同,更多详细信息也请参阅此答案:

from django.forms.models import model_to_dict

restaurant(place_ptr=place, **model_to_dict(place)).save()
Run Code Online (Sandbox Code Playgroud)

然而,由于 model_to_dict 返回的字段集有限,第二个风险更大(再次参见解释所提供的各种方法之间的差异的答案)。当然,它还会生成更多的数据库调用,因为它会写入两个表。