16

这些实现之间有什么区别?Django 有什么不同(除了继承 Metaorderingget_latest_by属性)?

1.

# models.py
from django.db import models

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

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

2.

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

class Restaurant(Place):
    serves_pizza = models.BooleanField()

3.

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

class Restaurant(Place):
    place = models.OneToOneField(Place, parent_link=True)
    serves_pizza = models.BooleanField()
4

2 回答 2

18

1.你并没有真正得到任何python继承,也就是说你不能从Place你的类中的模型类继承/覆盖方法或属性Restaurant

例如:

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

这意味着要获得name您不能做的餐厅的a_restaurant.name,您需要点击链接:a_restaurant.place.name

另请注意,在Place使用相关查询对象时Restaurant

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因为它们是继承的。

由于使用这些实现 aRestaurant 也是a Place,因此您也可以使用数据查询Place对象Restaurant

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()

工作原理完全相同,但要获得Restaurant属性名称的父位置是where

the_place = a_restaurant.where

2本来是:

the_place = a_restaurant.place_ptr

这些意味着place = models.OneToOneField(Place, parent_link=True)只会更改指向父模型实例的链接的名称。默认名称是'{lowercase_model_name}_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]

使用2-3

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]

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

于 2013-08-18T00:21:33.080 回答
3

1 - 要创建餐厅,您需要创建场所,创建餐厅后,链接它们,2 - 然后创建餐厅,新场所创建并自动链接,3 - 您将父链接重命名为场所。

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

于 2013-08-17T20:16:09.230 回答