Django queryset - 在对象上应用过滤器时,仅返回匹配manytomany记录

时间:2013-07-30 06:15:29

标签: django many-to-many django-queryset

我似乎无法找到一种方法来限制在对象上应用过滤器时返回的manytomany元素。如果有人能帮忙的话我真的很感激。

我们说我有以下型号:

## models.py

class Address(models.Model):
    street = models.CharField(max_length=128)
    city = models.CharField(max_length=128)
    state_province = models.CharField(max_length=128)
    zipcode = models.CharField(max_length=5)
    country = models.CharField(max_length=128)

class Venue(models.Model):
    address = models.ForeignKey(Address)
    phone_number = models.CharField(max_length=10)


class Event(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()
    venues = models.ManyToManyField(Venue)

现在,如果我有一个活动将在两个场地进行,一个活动在一个场地如下(为简化说明而简化):

e1 = Event1
e2 = Event2

v1 = Venue1
v2 = Venue2

e1.venues.add(v1,v2)
e2.venues.add(v1)

我想生成一个查询集,它可以恢复在Venue1' Venue1'只有' Venue1'作为返回场地的那些活动。

我试过了

event_list = Event.objects.filter(venues__address__city='CityVenue1')

但     event_list [0] .venues.all()

返回' Venue1'和' Venue2'。

我的偏好是:

  1. 过滤视图中的Event对象而不是Venue对象。
  2. 不通过模板中的标记/过滤器应用任何逻辑,并将其留在视图中以返回所需的查询集以提高性能 的原因。
  3. 我的模板按如下方式遍历事件列表:

    {% for event in event_list %}
        <p>event.name 
        {% for venue in event.venues.all %}
             at {{ venue.address.city }}
        {% endfor %}
        </p>
    {% endfor %}
    

    我希望它返回:

    Event1 at CityVenue1
    Event2 at CityVenue1
    

    但目前我得到

    Event1 at CityVenue1
           at CityVenue2
    
    Event2 at CityVenue1
    

    提前感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

当然你回到了两个场地,你正在查询模板中的所有场地。

{% for venue in event.venues.all %}

这一行执行一个全新的查询,抓住该活动的所有场地。

相反;在你看来,做你的过滤器并明确地传递你感兴趣的场地:

target_venue = Venue.objects.get(address__city='CityVenue1')
event_list   = target_venue.event_set.filter(name='EventName')

return render(request, 'events/event-list.html',
    {'Events': event_list, 'Venue': target_venue})

然后在你的模板中,

{% for Event in Events %}
    <p> {{ Event.name }} at {{ Venue.address.city }} </p>
{% endfor %}

编辑:通过@limelights

的建议改进

答案 1 :(得分:-1)

为什么你想在一个查询集中全部? Venue.objects.get(id=<id_venue1>).event_set.all()应该在一个查询集中返回链接到venue1的所有事件,并且您可以在另一个查询集中包含venue1。


您也可以使用 Venue.objects.get(id=<id_venue1>).values('adress', 'phone_number', 'event__name', 'event__description')得到类似下面的数组:

[
  { 'adress': '<venue1adress>', 'phone_number': '<venue1phone>', 'event__name': 'foo', 'event__description': 'I am a foo event'},
  { 'adress': '<venue1adress>', 'phone_number': '<venue1phone>', 'event__name': 'bar', 'event__description': 'I am a bar event'},
  ...
]

最后,我想,你也可以修改默认的查询集(因为它是一个python对象,而python对象可以做你想做的任何事情):

events_for_venur1 = Event.objects.filter(venues=venue1)
for event in events_for_venur1:
  for venue in event.venue_set:
    if venue != venue1:
      venue = None
# Here your queryset is ready, but DO NOT try to save it in the DB !!