2011-03-04 55 views
1

我有兩種基本模式,故事和類別:如何排除ManyToMany查詢中的當前對象?

class Category(models.Model): 
    title = models.CharField(max_length=50) 
    slug = models.SlugField() 
    ... 

class Story(models.Model): 
    headline = models.CharField(max_length=50) 
    slug = models.SlugField() 
    categories = models.ManyToManyField(Category) 
    ... 

而且我對故事的細節視圖:

from django.views.generic import date_based, list_detail 
from solo.apps.news.models import Story 

def story_detail(request, slug, year, month, day): 
""" 
Displays story detail. If user is superuser, view will display 
unpublished story detail for previewing purposes. 
""" 
stories = None 
if request.user.is_superuser: 
    stories = Story.objects.all() 
else: 
    stories = Story.objects.live() 
return date_based.object_detail(
    request, 
    year=year, 
    month=month, 
    day=day, 
    date_field='pub_date', 
    slug=slug, 
    queryset=stories, 
    template_object_name = 'story', 
) 

在一個給定的故事對象的觀點 - 我使用的是通用的細節視圖 - 我想通過應用於當前故事的類別顯示與當前故事相關的故事列表。

這裏是如何我目前在故事細節模板這樣做:

{% for category in story.category.all %} 
    <ul id="related_stories"> 
    {% for story in category.story_set.all|slice:"5" %} 
     <li><a href="{{ story.get_absolute_url }}" title="{{ story.headline }}">{{ story.headline }}</a></li> 
    {% endfor %} 
    </ul> 
{% endfor %} 

這爲我提供了我所需要的只是我想避免顯示爲我收視故事鏈接標題。

我相信這是通過「排除」過濾器完成的,但我不確定這是屬於類別還是故事模型作爲方法,或者如何構建它。

任何幫助,將不勝感激!

回答

0

這樣做:

class Story(models.Model): 
... 
    @property 
    def related_story_set(self): 
     category_id_list = self.category.values_list("id", flat=True) 
     return Story.objects.filter(category__id__in=category_id_list).exclude(id=self.id) 

然後你就可以在模板中做到這一點:

<ul id="related_stories"> 
{% for related_story in story.related_story_set.all|slice:"5" %} 
    <li><a href="{{ related_story.get_absolute_url }}" title="{{ related_story.headline }}">{{ related_story.headline }}</a></li> 
{% endfor %} 
</ul> 
+0

工程就像一個魅力,並與更少的代碼。在這種情況下,'flat = True'是做什麼的? – 2011-03-04 18:45:52

+0

啊,一個問題:如果你有兩個屬於同一兩個(或更多)類別的故事,你會在列表中得到重複的條目。任何想法如何過濾掉這些? – 2011-03-05 15:31:52

+0

實際上,如果我在故事對象查詢中調用'distinct()',它會出現過濾掉重複項。 – 2011-03-06 21:35:04

0

你可以簡單的模板,如果當前迭代的故事是原創的故事:

{% for category in story.category.all %} 
    <ul id="related_stories"> 
     {% for substory in category.story_set.all|slice:"5" %} 
      {% if substory != story %} 
       <li><a href="{{ substory.get_absolute_url }}" title="{{ substory.headline }}">{{ story.headline }}</a></li> 
      {% endif %} 
     {% endfor %} 
    </ul> 
{% endfor %} 

你要求把它放在一個模型方法:

class Story(models.Model): 
    ... 

    def get_categories_with_stories(self): 
     categories = self.category.all() 
     for category in categories: 
      category.stories = category.story_set.exclude(id=self.id)[:5] 
     return categories 

這並未解決昂貴的查詢問題,但這不是問題的一部分。

{% for category in story.get_categories_with_stories %} 
    <ul id="related_stories"> 
     {% for substory in category.stories %} 
       <li><a href="{{ substory.get_absolute_url }}" title="{{ substory.headline }}">{{ story.headline }}</a></li> 
     {% endfor %} 
    </ul> 
{% endfor %} 
+0

這樣的作品,但感覺像有太多的邏輯在模板中發生的事情。我如何將它移動到模型(以及哪個模型)上的方法? – 2011-03-04 14:40:18

+0

你說得對,這是視圖邏輯,所以它應該在你的視圖中(而不是模型),但我會發佈一個例子。 – 2011-03-04 14:50:03

+0

感謝您的示例。如果這是一個無知的問題,請原諒我,但是我如何在基於日期的通用細節視圖中使用它?然後,我如何在模板中訪問它? – 2011-03-04 15:32:59