Django ::引用外键

时间:2014-09-03 20:51:01

标签: python django one-to-many

我想创建一个页面,我可以在网页上按照图片显示属性。

目前,My Property模型看起来像这样(一些代码被取出):

class Property(models.Model):
    PROPERTY_TYPE = (('Room', 'Room'), ('House', 'House'))
    type = models.CharField(max_length=100, choices=PROPERTY_TYPE)
    title = models.CharField(max_length=100, db_index=True)
    beds = models.IntegerField(null=True, blank=True)
    price = models.IntegerField()
    payment_term = models.CharField(choices=PAYMENT_TERM_CHOICES, max_length=50)

和图片模型

class Picture(models.Model):
    location = models.CharField(max_length=255)
    owner = models.ForeignKey(User)
    active = models.BooleanField(default=True)
    alt = models.CharField(max_length=100)
    parent_property = models.ForeignKey(Property, null=True)
    timestamp = models.DateTimeField(default=timezone.now)

在我看来,我得到像这样的对象列表:

room_list = Property.objects.all().filter(type='Room').order_by('timestamp')[6]

当通过传递的room_list列表运行for循环时,我想像

一样引用它

会议室的第一张图片列表

我尝试过关于一对多关系的Django官方文档,但我似乎无法遵循它。

我将如何实现这一目标?

3 个答案:

答案 0 :(得分:1)

虽然你可以使用这样的东西:

{% for room in room_list %}
   <img src="{{ room.picture_set.first }}"/>
{% endfor %}

我不推荐它。原因是,对于每个room_list项,您将转到图片项的数据库。因此,当您有30个项目时,您将使用31个查询轰炸数据库。

你可以做的最简单的事情就是为你添加另一个字段属性模型,比如default_picture,默认情况下将FK添加到Picture with None。保存图片后,您将填写该图片的ID(您使用的图片以及如何处理没有图片的记录在您的业务逻辑上)。然后你就这样得到记录:

room_list = Property.objects.filter(
    type='Room'
).select_related(
    'default_picture'
).order_by('timestamp')[6]

这将导致单个查询。当然还有另一种方法可以达到同样的效果,但这些方法更复杂。

提示:您不需要按时间戳字段排序(除非您修改其值),但您可以使用ID,因为它是按顺序创建的。这是更便宜的操作(至少在Postgres中)。

更新: 正如@JamesLin建议的那样,你可以使用这样的东西:

room_list = Property.objects.filter(
    type='Room'
).prefetch_related(
    'picture_set'
)

这将被翻译成两个查询,一个用于Property列表,第二个用于与pull属性项相关的所有Picture记录(Django将以编程方式连接它们)。这对于程序员来说是相当懒惰的,但考虑到你正在为每个属性加载所有图片记录。但这肯定是比picture_set更好的解决方案,比我的第一个建议更容易实现(它不会自动意味着更好的解决方案)。

答案 1 :(得分:0)

room_list.picture_set.all()是您访问图片集的方式。要获得第一个,您只需访问room_list.picture_set.first()即可。模板版本:{{ room_list.picture_set.first }}

Relevant Django documentation

.first documentation

答案 2 :(得分:0)

在此处简单回答您的问题:

{% for room in room_list %}
   <img src="{{ room.picture_set.first }}"/>
{% endfor %}

然后有一整个chapter来优化它。

BTW:

此查询只会为您提供第7宫

room_list = Property.objects.all().filter(type='Room').order_by('timestamp')[6]

你可能想要[:6]

此外,您无需在.all()

之前致电.filter()
room_list = Property.objects.filter(type='Room').order_by('timestamp')[:6]