Django foreign keys queryset отображается в react-redux

Я знаю, что этот вопрос задавался много раз, но я не могу найти ответ на свою конкретную проблему. Я пытался добраться до решения как на бэкенде (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 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,
      })
  }
}


export const listCars = () => async (dispatch) => {
  try {
      
      dispatch({ type: CARS_LIST_REQUEST })

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

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

  } catch (error) {
      dispatch({
          type: CARS_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

Все изменения дадут вам подробную информацию о модели и марке,

Изменение в сериализаторе:

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)

Соответствующий бренд с каждой моделью будет автоматически добавлен в ответ.

Вернуться на верх