【问题标题】:Django foreign keys queryset displayed in react-reduxreact-redux 中显示的 Django 外键查询集
【发布时间】:2021-12-28 15:34:22
【问题描述】:

我知道这个问题被问了很多次,但我找不到具体问题的答案。我试图在后端(Django)和前端(React.js 和 Redux)上找到解决方案,但我找不到。

我正在尝试为汽车品牌和汽车型号制作一个简单的相关下拉列表,但我只能获取完整的型号列表,而不仅仅是与其品牌相关的型号。我是 Django 的新手,我不知道我的错误是我正在检索序列化程序中的所有数据,还是我弄错了外键关系。

如果您需要更多信息或解释,请告诉我。感谢您的帮助!

models.py:

class Brand(models.Model):
    name = models.CharField(max_length=120, unique=True)

    def __str__(self):
        return self.name

class Model(models.Model):
    brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, related_name='brand_id')
    name = models.CharField(max_length=120, unique=True)

    def __str__(self):
        return self.name

serializers.py:

class BrandSerializer(serializers.ModelSerializer):
    class Meta:
        model = Brand
        fields = '__all__'

class ModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Model
        fields = '__all__'

views.py:

@api_view(['GET'])
@permission_classes([AllowAny])
def getBrands(request):
    
    brands = Brand.objects.all()
    serializer = BrandSerializer(brands, many=True)
    
    return Response(serializer.data)

@api_view(['GET'])
@permission_classes([AllowAny])
def getModels(request):
    
    #This is wrong, but I don't know how to get the id from the car models match the id of the car brands
    brand_id = Brand.objects.filter('id').all() 
    models = Model.objects.filter(brand_id=brand_id).order_by('name')
    serializer = ModelSerializer(models, many=True)
    
    return Response(serializer.data)

urls.py:

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'),
    path('cars/model/', views.getModels, name='carmodels'),
    # path('cars/price/', views.getPrices, name='carprices'),
    
]

如果有帮助,这里是 React 代码:

reducers.js:

export const brandsList = (state = { brands: [] }, action) => {
  switch (action.type) {
      case BRANDS_LIST_REQUEST:
          return { loading: true, brands: [] }

      case BRANDS_LIST_SUCCESS:
          return {
              loading: false,
              brands: action.payload,
              
          }

      case BRANDS_LIST_FAIL:
          return { loading: false, error: action.payload }

      default:
          return state
  }
};


export const modelsList = (state = { models: [] }, action) => {
  switch (action.type) {
      case MODELS_LIST_REQUEST:
          return { loading: true, models: [] }

      case MODELS_LIST_SUCCESS:
          return { 
              loading: false,
              models: action.payload,
              
          }

      case MODELS_LIST_FAIL:
          return { loading: false, error: action.payload }

      default:
          return state
  }
};

actions.js:

export const listBrands = () => async (dispatch) => {
  try {
      
      dispatch({ type: BRANDS_LIST_REQUEST })

      const { data } = await API.get('/api/cars/brand/')

      dispatch({
          type: BRANDS_LIST_SUCCESS,
          payload: data
      })

  } catch (error) {
      dispatch({
          type: BRANDS_LIST_FAIL,
          payload: error.response && error.response.data.detail
              ? error.response.data.detail
              : error.message,
      })
  }
}


export const listModels = () => async (dispatch) => {
  try {
      
      dispatch({ type: MODELS_LIST_REQUEST })

      const { data } = await API.get('/api/cars/model/')

      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,
      })
  }
}

Dropdown.js:

import React, { useState, useEffect } from 'react'
import { useDispatch } 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;


  useEffect(() => {
    
    dispatch(listBrands());
    
    
    if ( brandId !== null ) {
      dispatch(listModels())
    };
    
  }, [dispatch])
    
      
    return (
      
        <div>
          
           
         <Form.Control 
            as="select"
            value={brandId ? brandId : ''}
            onChange={(e) => setBrandId(e.target.value)}
            >
            
                {

                  brands.map((brand) =>  
                        <option value={brand.id}>
                            {brand.name}
                        </option>
                    )
                }

            </Form.Control>
           
           
        
            <Form.Control 
            as="select"
            value={modelId ? modelId : ''}
            onChange={(e) => setModelId(e.target.value)}
            >
            
                {

                  models.map((model) =>  
                        <option value={model.id}>
                            {model.name}
                        </option>
                    )
                }

            </Form.Control>
          
      </div>
    )
}

export default Dropdown

【问题讨论】:

标签: python reactjs django django-rest-framework react-redux


【解决方案1】:

如此大的变化将为您提供模型和品牌的详细信息,

序列化程序的变化:

class ModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Model
        fields = '__all__'
        depth = 1 # new 

api 视图的变化:

@api_view(['GET'])
@permission_classes([AllowAny])
def getModels(request):
    models = Model.objects.all().order_by('name')
    serializer = ModelSerializer(models, many=True)
    return Response(serializer.data)

每个模型的相关品牌将自动添加到响应中。

【讨论】:

    猜你喜欢
    • 2015-03-09
    • 2015-01-25
    • 2013-09-27
    • 1970-01-01
    • 2018-04-29
    • 2013-09-17
    • 2015-07-30
    • 2020-10-22
    • 2018-07-06
    相关资源
    最近更新 更多