Django多模型:跟踪关系

时间:2010-07-21 17:02:54

标签: django django-models

我有一个多模型,它具有从不同模型到单个父模型的不同OneToOne关系。考虑这个例子:

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

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

class Shop(models.Model):
    place = models.OneToOneField(Place)
    ...

无论上述模型在现实生活场景中是否有意义,在django视图中,如何识别Place的对象是否与任何其他模型有关系?

2 个答案:

答案 0 :(得分:1)

在模板中,您可以说

{% if place.restaurant %}
    <!-- stuff goes here -->
{% endif %}

原因是OneToOneField条目实际上在它们引用的模型中创建了一个属性。在普通的Python代码中,说place.restaurant没有定义餐馆会引发异常,但模板会吞下这样的异常。

如果您确实需要在Python代码中执行类似的操作,最简单易懂的方法是将其包装在try / except块中:

place = Place.objects.all()[0]
try:
    restaurant = place.restaurant
    # do something with restaurant
except ObjectDoesNotExist:
    # do something without restaurant

编辑:正如我在评论中所说,如果您只希望Place成为RestaurantShop,而不是两者,那么您不应该使用OneToOneField,而应使用model inheritance

假设Place可能有两种或更多其他可能性,我建议做这样的事情:

class Place(Model):
    # define your fields here

    # you could generate this automatically with trickery
    OTHER_MODELS = ["restaurant", "shop"]

    @property
    def relationships(self):
        if not hasattr(self, "_relationships"):
            self._relationships = {}
            for attr in OTHER_MODELS:
                try:
                    self._relationshops[attr] = getattr(self, attr)
                except ObjectDoesNotExist:
                    pass
        return self._relationships

上面会让你说place.relationships并找回一个类似

的字典
{"restaurant": <Restaurant Object>, "shop": <Shop Object>}

虽然其中一个或两个可能会丢失,但取决于它们是否存在。这比使用每次扭转OneToOneField关系时必须捕获潜在异常更容易使用。

答案 1 :(得分:0)

由于Restaurant的外键指向Place,因此它会在类上留下related name字段,以便指向的类(Place)可以找到其内容:

# python
import yourproject.settings
from django.db.models.base import ObjectDoesNotExist
try:
  r = place.restaurant_set.get()
  do_something( r.restaurant_field )
except ObjectDoesNotExist:
  print "place has no restaurant"

从模板中,假设您可以以某种方式访问​​您的上下文中的placeobject

{% with placeobject.restaurant_set.get as r %}
  {% if r %}
    {{ r.restaurant_field }}
  {% else %}
    No restaurant
  {% endif %}
{% endwith %}