Django 循环返回多个帖子

Posted

技术标签:

【中文标题】Django 循环返回多个帖子【英文标题】:Django loop is returning multiple posts 【发布时间】:2017-11-02 06:10:01 【问题描述】:

我试图让 django 在该类别的页面上显示来自单个类别的帖子,而不是显示模板中每个类别下的所有类别和帖子。

这是我的模型(我把它们剪掉了):

class Category(models.Model):
    ...
    title = models.CharField(max_length=255, verbose_name="Title", null=True, blank=True)
    slug = models.SlugField(max_length=200, unique=True)


class Petition(models.Model):
    ...
    category = models.ManyToManyField(Category, verbose_name="Category", related_name='petitions')
    ...

views.py:

class CategoryMixin(object):
    def get_context_data(self, **kwargs):
        context = super(CategoryMixin, self).get_context_data(**kwargs)
        context['categories'] = Category.objects.all()
        return context


class CategoryView(CategoryMixin, generic.ListView):
    model = Category
    categories = Category.objects.all() # this will get all categories, you can do some filtering if you need (e.g. excluding categories without posts in it)
    queryset = Category.objects.all()
    template_name = 'petition/category_list.html'


class CategoryIndexView(generic.ListView):
    model = Category
    template_name = 'petition/category.html'
    context_object_name = 'category_list'

    def get_queryset(self): 
        return Category.objects.prefetch_related('petitions').order_by('-created_on')[:10]



class PetitionIndexView(generic.ListView):
    template_name = 'petition/home.html'
    context_object_name = 'petition_list'
    queryset = Petition.objects.order_by('-created_on')

    def get_queryset(self):
        queryset_list = Petition.objects.order_by('-created_on')

        #SEARCH QUERY LOGIC
        query = self.request.GET.get("q")
        if query:
            queryset_list = queryset_list.filter(
                Q(title__icontains = query) |
                Q(petition__icontains = query) |
                Q(created_by__first_name__icontains = query) | #icontains = only text fields. Use text field within foreign key field
                Q(created_by__last_name__icontains = query) 
                ).distinct()

        paginator = Paginator(queryset_list, 10) # Show 10 posts per page
        page = self.request.GET.get('page')

        try:
            queryset = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            queryset = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            queryset = paginator.page(paginator.num_pages)

        return queryset

        context = 
        'object_list' : queryset,
        'title' : 'List'
        

urls.py:

url(r'^$',views.PetitionIndexView.as_view(), name="homepage"),
url(r'^petition/(?P<slug>[\w-]+)/$',views.DetailView.as_view(), name="detail"),
url(r'^categories/$', views.CategoryView.as_view(), name='category_list'),
url(r'^category/(?P<slug>[\w-]+)/$',views.CategoryIndexView.as_view(), name="category_detail"),

而我的模板(CategoryIndexView 的category.html)就是这种格式,

category.html:

% for category in category_list %
    % for petition in category.petitions.all %
        ...
         petition.title 
        ...
    % end for %
% end for %

这会在同一模板中显示类别 A、B 和 C 中的帖子。

使用我设置的视图,当点击类别 A 时,如何让它只显示类别 A 的帖子?

此外,排序工作不正常。它不遵守我在视图中给它的顺序

【问题讨论】:

每次更改类别时都会执行模板中的django循环吗?我猜是这样,在那种情况下,类别列表变量会根据您刚刚切换到的类别而变化吗? 请显示您的网址。 @DanielRoseman 我已经添加了网址 @Strinnityk 是的,每次我更改类别时都会执行循环,但无论我在哪个类别页面上显示的内容都是相同的。 这些视图中的哪一个是应该这样做的?该模板指的是哪个视图? 【参考方案1】:

我猜每次更改类别时,整个循环都会再次执行,而不会更改 category_list 的内容(最初是 ["A", "B", "C"])。在这种情况下,即使您单击按钮更改类别,循环也会再次显示类别“A”、“B”和“C”的内容。

您是否尝试过添加一个 if 语句来检查您目前属于哪个类别并仅显示该类别中的帖子?

% for category in category_list %
  % if category.name == ACTUAL_CATEGORY_TO_DISPLAY %
    % for petition in category.petitions.all %
      ...
       petition.title 
      ...
     % end for %
  % end if %
% end for %

编辑:

正如@Daniel Roseman 在评论中指出的那样,这是一个非常低效的解决方案。我刚刚发布它是因为我猜测这是否真的发生在你身上。

如果是这种情况,您不应该这样做。正确的解决方案之一是发出一个新请求,每次更改时检索该给定类别的所有帖子。

无论如何,我只是在这里猜测。为了让我们更好地了解您,您应该发布更改类别的模板代码。

【讨论】:

虽然这可行,但它是一个非常低效的问题解决方案。为什么首先要遍历您不想要的类别?过滤应该在视图中完成。 @DanielRoseman 我知道,这是在不知道类别更改是如何完成的情况下想到的最快的解决方案。【参考方案2】:

您使用了错误的视图类。 ListView 是显示类的实例列表;所以 CategoryIndexView 将显示类别列表。但是您不想要类别列表;你想要一个单一的类别,以及它的请愿书列表。因此,您应该使用 DetailView。

class CategoryDetailView(generic.DetailView):
    model = Category
    template_name = 'petition/category.html'
    context_object_name = 'category'

    def get_queryset(self): 
        return Category.objects.prefetch_related('petitions')

而模板只是:

% for petition in category.petitions.all %
    ...
     petition.title 
    ...
% end for %

编辑:我将 context_object_name 从“category_list”更改为“category”,模板现在返回正确的帖子。

【讨论】:

它现在就像一个魅力。我的错误是在复制“ListViews”。感谢您的帮助。

以上是关于Django 循环返回多个帖子的主要内容,如果未能解决你的问题,请参考以下文章

Django框架模版渲染与过滤器使用

试图在我的存档页面中显示所有帖子,但它只返回页面内容

如何在Django视图中使用for循环返回每次迭代[关闭]

Python/Django 通过循环从变量创建几个类

从 Django 模型返回多个字段

Django更新每个用户的月度得分,并对其所有帖子进行总点赞