2017-06-30 27 views
2

我有一个Dj的Post模型与fk到Category模型与类别名称和类别slug。现在我通过django-filterLinkWidget按类别过滤这些帖子。这很好,并通过name="categories__name"工作开箱:django-filter:如何按字段A进行过滤,但将字段B显示为相应的过滤选项/文本?

# models.py 
class Category(models.Model): 
    name = models.CharField(max_length=255) 
    slug = models.SlugField(unique=True) 

class Post(models.Model): 
    categories = models.ManyToManyField(Category) 

# filters.py 
class PostFilter(django_filters.FilterSet): 

    categories = django_filters.AllValuesFilter(
     name="categories__name", 
     label="Categories", 
     widget=LinkWidget(), 
    ) 

    class Meta: 
     model = Post 
     fields = ['categories',] 

# template.html 

<h2>Filter</h2> 
{% for choice in filter.form.categories %} 
    {{ choice }}  
{% endfor %} 

<h2>Posts</h2> 
<ol> 
{% for obj in filter.qs %} 
    <li>{{ obj.title }}</li> 
{% endfor %} 

但现在我想以消除categories__name作为GET参数,并使用categories__slug代替 - 但保留作为LinkWidget中的链接文字的人类可读性更高categories__name - 但我不知道如何实现这一点,任何提示?

一些renderd HTML片段:

过滤通过name=categories__slug

<ul id="id_categories"> 
    <li><a href="?categories=audio-and-video">audio-and-video</a></li> 
    <li><a href="?categories=bits-bytes">bits-bytes</a></li> 
    <li><a href="?categories=foo-and-bar">foo-and-bar</a></li> 
</ul> 

过滤通过name=categories__name

<ul id="id_categories"> 
    <li><a href="?categories=Audio+and+Video">Audio and Video</a></li> 
    <li><a href="?categories=Bits%2FBytes">Bits/Bytes</a></li> 
    <li><a href="?categories=Foo+and+Bar">Foo and Bar</a></li> 
</ul> 

但我要的是(伪):

<li><a href="?categories={{ category.slug }}">{{ category.name }}</a></li> 

...并呈现:

<ul id="id_categories"> 
    <li><a href="?categories=audio-and-video">Audio and Video</a></li> 
    <li><a href="?categories=bits-bytes">Bits/Bytes</a></li> 
    <li><a href="?categories=foo-and-bar">Foo and Bar</a></li> 
</ul> 

或许更容易在一个最小的,完整的Django项目审查这个问题,所以我做了一个:https://gitlab.com/tombreit/django-filter-demo

版本:

  • 的Python 3.5 .3
  • Django(1.10.7)
  • django-filter(1.0.4)
+0

你确定它与'categories__name' GET参数开箱即用,但不是'类别='?你使用什么版本的Django过滤器? –

+0

由'categories__name'过滤并且'Category.name'是'Audio and Video',GET参数是'?categories = Audio + and + Video'。这工作。但我宁愿过滤'categories__slug',这将是'audio-and-video',但保留'category__name'字符串作为过滤器链接文本。更新了包含python软件包版本的问题。 – tombreit

回答

0

尝试这种解决方案:

class CustomAllValuesFilter(django_filters.ChoiceFilter): 
    @property 
    def field(self): 
     qs = self.model._default_manager.distinct() 
     qs = qs.order_by(self.name).values_list(self.name, self.extra['choice_name']) 
     del self.extra['choice_name'] 
     self.extra['choices'] = list(qs) 
     return super(CustomAllValuesFilter, self).field 


class PostFilter(django_filters.FilterSet): 
    categories = CustomAllValuesFilter(
     name="categories__slug", 
     label="Categories", 
     widget=LinkWidget(), 
     choice_name="categories__name" 
    ) 

    class Meta: 
     model = Post 
     fields = ['categories',] 
+0

对不起,我的模型定义中的错误 - 我更新了问题。我的问题中的代码是某种伪代码。 “真实”模型是通过'ParentalManyToManyField'链接到类别模型的w''页面模型。我尝试了你的建议,但设置'categories__name = django_filters.AllValuesFilter'导致整个过滤器消失... – tombreit

+0

我不熟悉w,,抱歉。有了Django的模型,就像在更新后的代码中一样,它按预期工作 - 显示已经与帖子链接的所有类别的段落。 –

+0

亲爱的@ sergey-zherevchuk,我建立了一个最小的django项目(没有w etc.等)。)来复制你的答案,但它不起作用,正如我以前的评论所述。如果您有时间空余,我恳请您看看这个演示项目。 gitlab存储库URL被添加到问题中。提前致谢。 – tombreit