Django 多表继承模型与同两个模型之间的简单一对一关系有什么区别?

Django 多表继承模型与同两个模型之间的简单一对一关系有什么区别?,django,inheritance,orm,model,Django,Inheritance,Orm,Model,这些实现之间的区别是什么?Django有什么不同之处(除了继承Metaordering和get\u latest\u by属性) 1. 2. 3. 1-要创建餐厅,您需要创建地点,在创建餐厅之后,在链接它们之后, 2-然后创建餐厅,创建并自动链接新场所, 3-您已将父链接重命名为place 使用带有内容类型的模型继承,您可以列出在Place.objects.all()上迭代的所有咖啡馆、餐馆、酒吧等。1。您实际上不会得到任何python继承,也就是说,您不能继承/重写类中模型类Place的方法或

这些实现之间的区别是什么?Django有什么不同之处(除了继承Meta
ordering
get\u latest\u by
属性)

1. 2. 3.
1-要创建餐厅,您需要创建地点,在创建餐厅之后,在链接它们之后, 2-然后创建餐厅,创建并自动链接新场所, 3-您已将父链接重命名为place


使用带有内容类型的模型继承,您可以列出在Place.objects.all()上迭代的所有咖啡馆、餐馆、酒吧等。

1。您实际上不会得到任何python继承,也就是说,您不能继承/重写类中模型类
Place
的方法或属性

例如:

class Place(models.Model):
    name = models.CharField(max_length=50)

    def get_x(self):
        return 'x'

class Restaurant(models.Model):
    place = models.OneToOneField(Place)
    serves_pizza = models.BooleanField()

a_restaurant = Restaurant()
a_restaurant.get_x() # -> wouldn't work
这意味着,要获取餐厅的
名称
,您不能执行
a_restaurant.name
,您需要遵循以下链接:
a_restaurant.place.name

还请注意,当查询带有相关餐厅的
Place
对象时

a_restaurant.save()
Place.objects.get(pk=a_restaurant.pk)  # won't work
你必须写:

a_restaurant.save()
Place.objects.get(restaurant__pk=a_restaurant.pk)

2和3。几乎一样。通过这些,您可以获得真正的python继承

a_restaurant = Restaurant()
a_restaurant.get_x() # would actually work and print 'x'
您的模型类
Restaurant
继承了
Place
中的所有内容:模型字段、普通实例/类属性、管理器、方法。。。您还可以覆盖其中的任何内容: 不支持覆盖字段属性。

因此,现在您可以直接从父模型获取字段的值:
a_restaurant.name
,因为它们是继承的

由于使用这些实现,
餐厅
也是一个
场所
,因此您可以使用
餐厅
数据查询
场所
对象:

a_restaurant.save()
the_place = Place.objects.get(pk=a_restaurant.pk)  
# ^ this works now and returns the equivalent `Place` instance.
the_same_restaurant = the_place.restaurant

如果为字段指定不同的名称,则2和3之间的差异更容易看出:

class Place(models.Model):
    name = models.CharField(max_length=50)

class Restaurant(Place):
    where = models.OneToOneField(Place, parent_link=True)
    serves_pizza = models.BooleanField()
工作原理完全相同,但要获取
餐厅的父位置
属性名称为
其中

the_place = a_restaurant.where
如果2,则:

the_place = a_restaurant.place_ptr
这意味着
place=models.OneToOneField(place,parent\u link=True)
将只更改链接到父模型实例的名称。默认名称是
{lowercase\u model\u name}\u ptr'


最后一个例子:

使用1

place1 = Place.objects.create(name='place_1')
place2 = Place.objects.create(name='place_2')
restaurant1 = Restaurant.objects.create(place=place1, serves_pizza=True)

print Place.objects.all() # prints [place1, place2]
print Restaurant.objects.all() # prints [restaurant1]
place1 = Place.objects.create(name='place_1')
place2 = Place.objects.create(name='place_2')
restaurant1 = Restaurant.objects.create(name='place_3', serves_pizza=True)

print Place.objects.all() # prints [place1, place2, place3]
print Restaurant.objects.all() # prints [restaurant1]
使用2-3

place1 = Place.objects.create(name='place_1')
place2 = Place.objects.create(name='place_2')
restaurant1 = Restaurant.objects.create(place=place1, serves_pizza=True)

print Place.objects.all() # prints [place1, place2]
print Restaurant.objects.all() # prints [restaurant1]
place1 = Place.objects.create(name='place_1')
place2 = Place.objects.create(name='place_2')
restaurant1 = Restaurant.objects.create(name='place_3', serves_pizza=True)

print Place.objects.all() # prints [place1, place2, place3]
print Restaurant.objects.all() # prints [restaurant1]


希望这些有帮助。它变得有点太长了://

我个人的意见:2º选项似乎是这个示例的最佳实现,因为
餐厅
确实是一个
地方
。非常好的解释,我没想到会这么长:)谢谢!注意:在Django 1.5中,子模型的OneToOneField的默认名称是
objectname.parentobject\u ptr
(不是objectname.parentobject)。因此,您可以使用
a_餐厅查询地点。Place_ptr
in#2。但是另一种方式(从地点查询)是:
a_place.restaurant
@Adrian你必须写:a_restaurant.save()place.objects.get(restaurant_upk=a_restaurant.pk)如果餐馆来自/包含地点,而不是反过来,我不明白我们如何写restaurant_upk。Thanks@dowjones123Django可以向后跟踪(和查询)关系。看一看,特别是我想用额外的字段扩展内置站点框架站点模型,并尝试决定哪种方法最好。
place1 = Place.objects.create(name='place_1')
place2 = Place.objects.create(name='place_2')
restaurant1 = Restaurant.objects.create(name='place_3', serves_pizza=True)

print Place.objects.all() # prints [place1, place2, place3]
print Restaurant.objects.all() # prints [restaurant1]