我有一个Django Post
模型,其fk为Category
模型,带有类别名称和类别slug。现在,我通过django-filter和LinkWidget按类别过滤这些帖子。这很好,通过name="categories__name"
开箱即用:
# 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
代替 - 但保持人类可读性categories__name
作为LinkWidget
中的链接文字} - 但我不知道如何实现这一点,任何提示?
一些渲染的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
版本:
答案 0 :(得分: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',]