Django 反向查找外键

110
我有一个场地,这个场地上有很多活动。我的模型看起来像这样:
class Venue(models.Model):
    title = models.CharField(max_length=200)
    date_published = models.DateTimeField('published date',default=datetime.now, blank=True)
    venue_latitude = models.CharField(max_length=200)
    venue_longitude = models.CharField(max_length=200)
    venue_address = models.CharField(max_length=200)
    venue_city = models.CharField(max_length=200)
    venue_state = models.CharField(max_length=200)
    venue_country = models.CharField(max_length=200)
    description = models.TextField()
    def __unicode__(self):
        return u'%s' % (self.title)

class Event(models.Model):
    title = models.CharField(max_length=200)
    date_published = models.DateTimeField('published date',default=datetime.now, blank=True)
    date_start = models.DateTimeField('start date')
    date_end = models.DateTimeField('end date')
    def __unicode__(self):
        return self.title
    description = models.TextField()
    price = models.IntegerField(null=True, blank=True)
    venue = models.ForeignKey(Venue)

我想要显示在某个场地发生的所有活动。我该怎么做?我的当前视图如下:

def detail(request, venue_id):
    venue = get_object_or_404(Venue, pk=venue_id)
    return render(request, 'venue-detail.html', {'venue': venue})

这些字段与哪个模块相关?description = models.TextField()? - donkeyboy72
实际上,这两个模型分别在它们自己的应用程序中,我只是将它们一起发布以解释这一点 :) - FLX
4个回答

173
您可以使用events = venue.event_set来实现反向查询。
请注意,venue.event_set是一个管理器对象,就像Event.objects一样,因此您可以在其上调用.all.filter.exclude等方法以获取查询集。
请参阅Django文档

太好了!谢谢你。但是,如果我想要遍历这些事件(for i in events),我会得到“'RelatedManager' object is not iterable”的错误提示。 - FLX
你是如何将它改成QueryObject的? - mp3por
7
通常情况下,使用@mp3por venue.event_set.all()或venue.event_set.filter()。 - aptwebapps
5
如果有人仍然看到错误消息“AttributeError: 'Foo' object has no attribute 'bar_set'”,可能需要检查子模型(Bar)中指向父模型(Foo)的ForeignKey/OneToOneField/ManyToManyField是否设置了related_name。请注意不改变原意,使翻译通俗易懂,不添加任何额外内容。 - Bartleby
这个查找会快吗?他应该给场馆添加外键吗?这样会更快吗? - Sion C
显示剩余2条评论

10

针对那些出现 "'RelatedManager' object is not iterable" 错误的人

添加 "all" 以从管理器中检索所有元素。

{% for area in world_areas.all %}

https://dev59.com/g2w15IYBdhLWcg3wT51c#16909142 (无法在第一个回答的评论中添加此内容)


你刚刚救了我的一天 链接 - shaan
1
我在找到这个之前,准备在我的模型中制造混乱 :D - PowerAktar

6

反其道而行之。使用 Event 模型。

def detail(request, venue_id):
    venue = Event.objects.filter(venue__id=venue_id)
    return render(request, 'venue-detail.html', {'venue': venue})

PS:我从未使用过get_object_or_404()。请相应修改代码。


那么我在模板中可以使用什么来显示场馆标题和在此场馆举行的所有活动呢? - FLX
1
在模板中使用 {{ event.venue.title }} 或根据您的变量使用 {{ venue.venue.title }} :) {% for i in venue %} {{ i.venue.title }} - rjv
我明白,但是我如何显示在这个场馆发生的所有事件? - FLX
筛选器返回一个包含在场地发生的所有事件的数组。在模板中使用for循环遍历该数组。 - rjv
2
venue = Event.objects.filter(venue__id=venue_id) 我认为这个表达式将返回Event对象的QuerySet而不是Venue对象。 - smilingwang
@smilingwang,请仔细阅读所提出的问题。 - boatcoder

1
你可以使用venue.event_set.all()来获取在某个场馆举行的所有活动,如下所示:
def detail(request, venue_id):
    venue = get_object_or_404(Venue, pk=venue_id)
    events = venue.event_set.all() # Here
    return render(request, 'venue-detail.html', {'events': events})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接