Django+React-Redux实现汽车品牌车型级联下拉筛选异常求助
问题根源
后端车型查询接口未接收品牌筛选参数,前端选中品牌后未传递品牌ID到后端,也未监听品牌ID变化触发车型列表重新拉取。
后端修改
1. urls.py
修改车型接口路由,支持接收品牌ID参数:
from django.urls import path from . import views urlpatterns = [ path('users/', views.UserProfile.as_view()), path('user/<int:pk>/', views.UserProfile.as_view()), path('cars/brand/', views.getBrands, name='carbrands'), # 修改为带brand_id参数的路由 path('cars/model/<int:brand_id>/', views.getModels, name='carmodels'), # path('cars/price/', views.getPrices, name='carprices'), ]
2. views.py
修改getModels视图逻辑,接收品牌ID并过滤对应车型:
@api_view(['GET']) @permission_classes([AllowAny]) def getModels(request, brand_id): # 直接用传入的brand_id过滤关联车型 models = Model.objects.filter(brand_id=brand_id).order_by('name') serializer = ModelSerializer(models, many=True) return Response(serializer.data)
可选优化(不影响功能)
Model类外键的related_name命名语义可以调整,related_name是反向查询时用的属性名,当前命名为brand_id不符合语义,建议修改为:
class Model(models.Model): # 把related_name改为models,后续反向查询写法为Brand.objects.first().models.all() brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, related_name='models') name = models.CharField(max_length=120, unique=True) def __str__(self): return self.name
前端修改
1. actions.js
修改listModels方法,支持传入品牌ID作为请求参数:
export const listModels = (brandId) => async (dispatch) => { try { dispatch({ type: MODELS_LIST_REQUEST }) // 把品牌ID拼到请求路径中 const { data } = await API.get(`/api/cars/model/${brandId}/`) dispatch({ type: MODELS_LIST_SUCCESS, payload: data }) } catch (error) { dispatch({ type: MODELS_LIST_FAIL, payload: error.response && error.response.data.detail ? error.response.data.detail : error.message, }) } }
2. Dropdown.js
补充缺失导入,修改依赖监听、请求触发逻辑:
import React, { useState, useEffect } from 'react' // 补充导入useSelector import { useDispatch, useSelector } from 'react-redux' import { Row, Col, ListGroup, Button, Form } from 'react-bootstrap' import options from "../../utils/Options" // Redux action import { listBrands, listModels, listCars } from "../../store/actions"; function Dropdown() { const [brandId, setBrandId] = useState(null); const [modelId, setModelId] = useState(null); const dispatch = useDispatch(); const brandsList = useSelector(state => state.brandsList); const { error, loading, brands } = brandsList; const modelsList = useSelector(state => state.modelsList); const { models } = modelsList; // 依赖添加brandId,品牌变化时自动触发重新拉取车型 useEffect(() => { dispatch(listBrands()); if ( brandId !== null ) { // 传入选中的品牌ID拉取对应车型 dispatch(listModels(brandId)) // 切换品牌时清空已选车型 setModelId(null) }; }, [dispatch, brandId]) return ( <div> <Form.Control as="select" value={brandId ? brandId : ''} // 转成数字类型,避免字符串ID和后端int类型不匹配 onChange={(e) => setBrandId(Number(e.target.value))} > { brands.map((brand) => <option value={brand.id} key={brand.id}> {brand.name} </option> ) } </Form.Control> <Form.Control as="select" value={modelId ? modelId : ''} onChange={(e) => setModelId(Number(e.target.value))} > { models.map((model) => <option value={model.id} key={model.id}> {model.name} </option> ) } </Form.Control> </div> ) } export default Dropdown
内容的提问来源于stack exchange,提问作者EMCarlos
相关产品推荐
相关产品推荐

