使用Django Filter实现分类筛选报错求助:Field 'id'类型错误
解决Django Filter分类筛选的"Field 'id' expected a number"错误
问题描述
我在给Django项目用Django Filter添加分类筛选功能时,先后遇到两个错误:
Field 'id' expected a number but got 'blogs'.
Field 'id' expected a number but got 'new'.
以下是我的相关代码:
博客模型
class blog(models.Model): title = models.CharField(max_length=100, null=True, blank=True) slug = models.SlugField(max_length=200, unique=True, auto_created=True) author = models.ForeignKey(User, on_delete=models.CASCADE) created_on = models.DateTimeField(auto_now_add=True) tags = TaggableManager(blank=True) category = models.ForeignKey('Categorie', null=True, blank=True, on_delete=models.CASCADE)
分类模型
class Categorie(models.Model): name = models.CharField(max_length=100, null=True, blank=True) slug = models.SlugField(max_length=250, unique=True, auto_created=True)
filters.py文件
blog_choice = ( ('new','new'), ('latest','latest'), ('technology','technology'), ('sports','sports'), ) category = django_filters.MultipleChoiceFilter(label='Category', choices=blog_choice, widget=CheckboxSelectMultiple(attrs={'class': 'mr-2 h-[15px] w-5 border-gray-300 inline mb-4 '}))
问题原因及解决方法
核心问题
category是外键字段,默认会按关联模型的id匹配筛选值,但你传入的是字符串(如'new'),导致类型不匹配报错。- 硬编码的
blog_choice和实际数据库中的分类数据脱节,无法正确关联分类模型。
正确实现步骤
1. 修正filters.py,关联分类模型实现筛选
用ModelMultipleChoiceFilter直接绑定Categorie模型,支持多选分类:
import django_filters from django.forms import CheckboxSelectMultiple from .models import blog, Categorie class BlogFilter(django_filters.FilterSet): category = django_filters.ModelMultipleChoiceFilter( queryset=Categorie.objects.all(), label='分类', widget=CheckboxSelectMultiple(attrs={'class': 'mr-2 h-[15px] w-5 border-gray-300 inline mb-4 '}), # 按分类名称匹配,而非默认的id field_name='category__name', to_field_name='name' ) class Meta: model = blog fields = ['category']
2. 兼容自定义筛选选项(如new/latest)
如果需要保留'new'/'latest'这类时间排序筛选,单独添加自定义筛选器:
import django_filters from django.forms import CheckboxSelectMultiple, ChoiceField from .models import blog, Categorie class BlogFilter(django_filters.FilterSet): # 分类筛选 category = django_filters.ModelMultipleChoiceFilter( queryset=Categorie.objects.all(), label='分类', widget=CheckboxSelectMultiple(attrs={'class': 'mr-2 h-[15px] w-5 border-gray-300 inline mb-4 '}), field_name='category__name', to_field_name='name' ) # 时间排序筛选 sort_by = django_filters.ChoiceFilter( choices=( ('new', '最新发布'), ('latest', '最近更新'), ), label='排序', method='filter_sort_by' ) def filter_sort_by(self, queryset, name, value): if value == 'new': return queryset.order_by('-created_on') elif value == 'latest': # 若需要按更新时间排序,需先给blog模型添加updated_on字段 return queryset.order_by('-created_on') return queryset class Meta: model = blog fields = ['category', 'sort_by']
3. 在视图中使用FilterSet
from django.shortcuts import render from .models import blog from .filters import BlogFilter def blog_list(request): filter = BlogFilter(request.GET, queryset=blog.objects.all()) return render(request, 'blog_list.html', {'filter': filter})
4. 模板中渲染筛选表单
<form method="get"> {{ filter.form.as_p }} <button type="submit">筛选</button> </form> {% for post in filter.qs %} <div>{{ post.title }} - {{ post.category.name }}</div> {% endfor %}
额外注意事项
- 模型名建议遵循Python规范,改为大写开头(如
Blog、Category)。 - 若要按分类的slug筛选,只需将
field_name改为category__slug,to_field_name改为slug。 - 确保
Categorie模型中已添加对应分类数据(如'technology'、'sports'),否则筛选器无法获取选项。
内容的提问来源于stack exchange,提问作者WalterW
相关产品推荐
相关产品推荐

