You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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 '}))

问题原因及解决方法

核心问题

  1. category是外键字段,默认会按关联模型的id匹配筛选值,但你传入的是字符串(如'new'),导致类型不匹配报错。
  2. 硬编码的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 07:05:22