如何在 django 的单个视图中显示多个 ForeignKey 过滤项目?

Posted

技术标签:

【中文标题】如何在 django 的单个视图中显示多个 ForeignKey 过滤项目?【英文标题】:How to display multiple ForeignKey filtered items in a single view in django? 【发布时间】:2016-01-15 05:25:03 【问题描述】:

我试图了解在 Django 模型中显示 ForeignKey 过滤数据的最佳方式。

我将三个模型简化为:

// models.py
class Publisher(models.Model)
    def publisher_name = models.TextField()
    def publisher_slug = models.SlugField()
    def founded_year = models.IntegerField()

class Album(models.Model)
    def album_name = models.TextField()
    def publisher = models.ForeignKey('Publisher', related_name='albums')

class Song(models.Model)
    def song_name = models.TextField()
    def album = models.ForeignKey('Album', related_name='songs')
    def published_year = models.IntegerField()

我有一个由以下内容组成的 URL:/<publisher>/<published_year>/

我在撰写时遇到问题的视图应该是这样的细节:

标题:Publisher.publisher_name 出版商的所有专辑列表:该专辑中与出版商同年出版的所有歌曲列表__published_year:该专辑中作为网址发布的所有歌曲列表

我现在尝试这样做的方式与此类似:

// views.py
class SongYearView(TemplateView):
    def get_context_data(self, **kwargs):
        context = super(SongYearView, self).get_context_data(**kwargs)
        context['publisher'] = Publisher.objects.get(slug=kwargs['publisher_slug']
        album_list=[]
        for album in context['publisher'].albums.all():
            single_album = dict()
            single_album['album'] = album
            single_album['publisher_year_song'] = album.songs.filter(published_year=context['publisher'].published_year)
            single_album['filtered_year_song'] = album.songs.filter(published_year=kwargs['published_year']
            album_list.append(single_album)
        context['albums'] = album_list
        return context

然后在我正在做的模板中(去除格式)

// template.html
 publisher.name 
% for album in albums %
      album.album.album_name 

    % for song in album.publisher_year_song %
         song.song_name 
    % endfor %

    % for song in album.filtered_year_song %
         song.song_name 
    % endfor %
% endfor %

虽然这确实有效,但它并不漂亮,我很确定有更好的方法来做到这一点。

这是一个奇怪的例子,但只是我更详细模型的一个基本例子。考虑它的方式是出版商->专辑->歌曲或A->B->C。我试图查看所有B项目,这些项目只与特定的A项目链接,然后得到两个每个 B 项的 C 项集合,其中一组根据 A 属性过滤,另一组根据来自 URL 的传递参数进行过滤。

我试图获得一个自定义 model.Manager 来帮助构建它,但运气不佳。

【问题讨论】:

我想知道这是否应该更好地放在Code review 啊,我不知道代码审查部分。这个查询更多地表明我已经尝试了一些东西,但我想知道编程场景的正确方法。 由于您的代码工作正常,它完全符合代码审查指南,但您的说明可能要少得多......(我认为,在 SO 上发布它仍然很好) 我重命名了模板过滤器:我觉得这样更好。 (如果我的回答解决了您的问题,请将其标记为已接受 - 检查箭头附近) 【参考方案1】:

你可以做add a custom template filterof_year:

@register.filter
def of_year(songs, year):
    return songs.filter(published_year=year)

并将您的模板更改为

// template.html
 publisher.name 
% for album in publisher.albums %
      album.album.album_name 

    % for song in album.songs|of_year:publisher.founded_year %
         song.song_name 
    % endfor %

    % for song in album.songs|of_year:filtered_year %
         song.song_name 
    % endfor %
% endfor %

并清理您的视图:

// views.py
class SongYearView(TemplateView):
    def get_context_data(self, **kwargs):
        context = super(SongYearView, self).get_context_data(**kwargs)
        context['publisher'] = Publisher.objects.get(slug=kwargs['publisher_slug'])
        context['filtered_year'] = kwargs['published_year']
        return context

编辑:重命名模板过滤器

【讨论】:

以这种方式使用过滤器是正确的方法吗?这不是通过自定义模型管理器更好地处理吗?正如我所读到的,模板应该避免使用功能。 我在 django 方面做得不够好,无法通过自定义模型管理器来处理它。 As I've read that the templates should avoid functionality.我确实同意这个观点,我认为在你的情况下,过滤更多地与演示文稿(模板)有关,而不是模型(我试图将我的过滤器限制为一个额外的参数和 2 行代码)

以上是关于如何在 django 的单个视图中显示多个 ForeignKey 过滤项目?的主要内容,如果未能解决你的问题,请参考以下文章

Django 表单:查询结果定义的字段,单个视图同时更新多个对象

我可以在 django 中的单个表单中使用多个表单集,如果可以的话如何?

从 django 中的单个视图呈现多个模板

有没有一种方法可以在 Django 的同一个模板中呈现多个视图?

在Django模板中使用for循环显示多个chart.js图表

Django 以 JSON 格式返回单个记录