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

Django+Ajax实现商品过滤时出现Field 'id'类型不匹配错误求助

商品筛选Ajax请求报错:Field 'id' expected a number but got 'filter_data' 修复方案

问题场景

开发商品筛选功能,引入Ajax实现多类别卡片筛选,原本功能正常,添加数据处理和JsonResponse后,点击筛选复选框触发错误:ValueError: Field 'id' expected a number but got 'filter_data'。

错误原因

Django的URL路由匹配是从上到下依次匹配,你的urls.py中,path('<str:id>', views.product_view, name="product_view")这个路由定义在filter_data路由的前面。当Ajax请求/filter_data/时,Django会先匹配到<str:id>这个路由,把字符串filter_data作为id参数传递给product_view视图。而视图中用这个字符串去查询Product的id(整数类型字段),就会抛出类型不匹配的错误。

修复步骤

1. 调整URL路由顺序

把filter_data的路由移到<str:id>路由的前面,确保Django先匹配到明确的筛选路由,不会被通用的id路由捕获。

修改后的urls.py:

from django.urls import path, include
from django.contrib.auth.views import PasswordChangeView
from . import views
from .forms import PasswordUpdateForm

urlpatterns = [
    path('', views.store, name="store"),
    path('cart/', views.cart, name="cart"),
    path('checkout/', views.checkout, name="checkout"),
    path('login/', views.loginPage, name="login"),
    path('logout/', views.logoutUser, name="logout"),
    path('registration/', views.registrationPage, name="registration"),
    path('profile/', views.profile, name="profile"),
    path('change_password/', PasswordChangeView.as_view(template_name='store/change_password.html', success_url='profile', form_class=PasswordUpdateForm ), name="change_password"),
    path('change_password/profile/', views.profile, name="profile"),

    path('update_item/', views.updateItem, name="update_item"),
    path('update_wish_item/', views.updateWishItem, name="update_wish_item"),
    path('process_order/', views.processOrder, name="process_order"),
    # 把filter_data路由移到前面
    path('filter_data/', views.filter_data, name="filter_data"),
    path('wishlist/', views.wishlist, name="wishlist"),
    path('search/', views.search, name="search"),
    # 通用id路由放在最后
    path('<str:id>', views.product_view, name="product_view"),
    path('search/<str:id>',views.product_view, name="product_view"),
]

2. 优化product_view的路由参数(可选但推荐)

因为Product的id是整数类型,把路由参数改成<int:id>,这样只有数字字符串会被匹配,避免类似的字符串参数错误:

修改路由:

path('<int:id>', views.product_view, name="product_view"),
path('search/<int:id>',views.product_view, name="product_view"),

同时修改views.py中的product_view函数参数类型:

def product_view(request, id: int):
    product = Product.objects.filter(id=id).first()
    # 其余代码不变

3. 完善filter_data视图的筛选逻辑

当前filter_data只是返回固定字符串,需要实现实际的筛选逻辑,根据Ajax传递的筛选参数过滤商品:

修改views.py中的filter_data:

from django.shortcuts import render
from django.http import JsonResponse

def filter_data(request):
    # 获取Ajax传递的筛选参数
    filters = request.GET.dict()
    # 构建查询条件
    query = Product.objects.all()
    
    # 处理颜色筛选
    if 'color' in filters and filters['color']:
        query = query.filter(color_id__in=filters['color'].split(','))
    # 处理尺寸筛选
    if 'size' in filters and filters['size']:
        query = query.filter(size_id__in=filters['size'].split(','))
    # 处理品牌筛选
    if 'brand' in filters and filters['brand']:
        query = query.filter(brand_id__in=filters['brand'].split(','))
    # 处理性别筛选
    if 'gender' in filters and filters['gender']:
        query = query.filter(gender__in=filters['gender'].split(','))
    
    # 把查询结果渲染成HTML片段(需要创建对应的模板片段)
    html = render(request, 'store/product_card.html', {'products': query}).content.decode('utf-8')
    
    return JsonResponse({'data': html})

需要创建store/product_card.html模板,用来渲染单个商品卡片,示例:

{% for product in products %}
<div class="product-card">
    <img src="{{ product.imageURL }}" alt="{{ product.name }}">
    <h3>{{ product.name }}</h3>
    <p>价格:{{ product.price }}</p>
    <a href="{{ product.id }}">查看详情</a>
</div>
{% endfor %}

验证修复

修改完成后,重启Django服务,点击筛选复选框,Ajax请求会正确路由到filter_data视图,返回筛选后的商品HTML片段,替换页面中的#filteredProducts内容,不会再触发id类型错误。

内容的提问来源于stack exchange,提问作者Poor Cake

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:13:08