2013-08-07 34 views
0

我想过滤Django中的一个对象,并将其与任何结果为ForeignKey的对象一起返回。我不确定注释是否是我需要的,或其他。用foreignkey注释结果

这是我的模型:

class Dress(models.Model): 
    name = models.CharField(...) 
    price = models.FloatField(...) 

class ClothingSize(models.Model): 
    code = models.CharField(...) 

class DressSizeAvailable(models.Model): 
    dress = models.ForeignKey(Dress) 
    size = models.ForeignKey(ClothingSize) 

说我要过滤所有的礼服在50 $,然后与现有的尺寸显示。做这个的最好方式是什么?

我得尽可能的:

# In view 
results = Dress.objects.filter(price__lt=50) 
# How to annotate with available sizes? 

# In template 
{% for result in results %} 
    {{ result.name }}, ${{ result.price }} 
    Sizes: {{ ??? }} 
{% endfor %} 

回答

1
### 1st solution (similar to Daniel Rosenthal's answer but with performances concern) 
results = DressSizeAvailable.objects.filter(dress__price__lt=50).select_related('dress', 'size') 
# then you can browse your DressSizeAvailables as you wish in your template. The select related allows you NOT TO query the database again when you generate your template 

### 2nd solution 
results = Dress.objects.filter(price__lt=50).prefetch_related('dresssizeavailable_set__dress') 

{% for dress in results %} 
    {{ dress.name }}, ${{ dress }} 
    Sizes: <ul> 
     {% for dsa in dress.dresssizeavailable_set %} 
      <!-- Thanks to the prefetch_related, we do not query the base again here --> 
      <li>{{ dsa.size.code }}</li> 
     {% endfor %} 
    </ul> 
{% endfor %} 
+0

谢谢!我只需要在'{%for dsa in dress.dresssizeavailable_set.all%}'末尾加上'all'就可以工作。 – Richard

0

你需要给你的模板查询集(或类似的东西)DressSizeAvailable对象。因此,首先你需要把所有的Dress对象你有兴趣,然后根据这些礼服

所以在您的视图筛选DressSizeAvailable

dresses = Dress.objects.filter(price__lt=50) 
dress_size_available = [] 
for dress in dresses: 
    available = DressSizeAvailable.objects.filter(dress=dress) 
    dress_size_available.append(available) 

然后渲染你的模板,它传递变量dress_size_available

您的模板可以很简单。

{% for dsa in dress_size_available %} 
    {{ dsa.dress.name }}, ${{ dsa.dress.price }} 
    Size: {{ dsa.size }} 
{% endfor %} 
+0

__in views.py:__在第1行一个DB查询,anothor对于每次迭代=> N + 1 DB查询。 __在template.html:__ 3查询for循环的每个迭代=> 3N DB查询。 __Total:__ 1 + 4N查询您的数据库!我猜你的数据库与你的应用服务器在同一主机上,否则你的演出将会很差:) – Ricola3D

+0

是的,我要问 - 是不是迭代查询集效率低下? – Richard

+0

为了在迭代查询集时高效,请确保为直接外键添加__select_related()__,为反向外键和m2m关系添加__prefetch_related()__。在这里查看他们的文档:https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related。每当你从一个查询集的对象中调用“。”时,如果你没有使用这两个函数将它们包含在查询集中,那么Django将为它们重新获取数据库。 – Ricola3D