Поместите параметры запроса в url запрос Django

У меня есть запрос, который извлекает все данные, но я хотел бы сделать другой запрос с другим url, добавив параметры запроса, чтобы нацелить поиск данных. Например, когда я запрашиваю следующий url:

http://localhost:8000/api/calendars

У меня такой результат:

 [
  {
    "id": 1,
    "plant_step_id": [
      {
        "id": 3,
        "plant_id": {
          "id": 1,
          "name": "Agropyre"
        },
        "step_title": "Sowing"
      }
    ],
    "start": [
      1
    ],
    "end": [
      3
    ]
  },
  {
    "id": 2,
    "plant_step_id": [
      {
        "id": 6,
        "plant_id": {
          "id": 6,
          "name": "Aubergine"
        },
        "step_title": "Planting"
      }
    ],
    "start": [
      6
    ],
    "end": [
      7
    ]
  }
]

И я хотел бы, запросив этот url:

http://localhost:8000/api/plant/life/calendars?plant_id=1&step_title=Посев

Я хотел бы получить данные о том, что я запросил в url.

Я пытался добиться этого в представлении, но ничего не вышло.

Вот модель:

from django.db import models
from multiselectfield import MultiSelectField

MONTHS = (
    (1, 'January'),
    (2, 'February'),
    (3, 'March'),
    (4, 'April'),
    (5, 'May'),
    (6, 'June'),
    (7, 'July'),
    (8, 'August'),
    (9, 'September'),
    (10, 'October'),
    (11, 'November'),
    (12, 'December')
)

class PlantLifeCalendar(models.Model):
    plant_step_id = models.ManyToManyField('perma_plant_steps.PlantStep')
    start = MultiSelectField(choices=MONTHS, max_choices=3, max_length=6)
    end = MultiSelectField(choices=MONTHS, max_choices=3, max_length=6)

Вот сериализатор:

class PlantSerializer(serializers.ModelSerializer):
    class Meta:
        model = Plant
        fields = ('id', 'name',)

class PlantStepSerializer(serializers.ModelSerializer):
    plant_id = PlantSerializer()

    class Meta:
        model = PlantStep
        fields = ('id', 'plant_id', 'step_title')
        
class ReadPlantLifeCalendarSerializer(serializers.ModelSerializer):
    plant_step_id = PlantStepSerializer(read_only=True, many=True)
    start = fields.MultipleChoiceField(choices=MONTHS)
    end = fields.MultipleChoiceField(choices=MONTHS)

    class Meta:
        model = PlantLifeCalendar
        fields = '__all__'
        read_only_fields = [fields]

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

Вот вид:

class PlantLifeCalendarViewSet(viewsets.ModelViewSet):
    # permission_classes = (IsAuthenticated,)
    permission_classes = (AllowAnonymous,)
    queryset = PlantLifeCalendar.objects.prefetch_related('plant_step_id').all()

    def create(self, request, *args, **kwargs):
        serializer = WritePlantLifeCalendarSerializer(data=request.data, many=isinstance(request.data, list))
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def get_serializer_class(self):
        if self.action in ("list", "retrieve"):
            return ReadPlantLifeCalendarSerializer
        return WritePlantLifeCalendarSerializer


class PlantLifeCalendarLinkAPIView(ListAPIView):
permission_classes = (AllowAnonymous,)
serializer_class = ReadPlantLifeCalendarSerializer

def get_queryset(self):
    try:
        plant_id = int(self.request.GET.get('plant_id'))
    except (ValueError, TypeError):
        plant_id = None
    step_title = self.request.GET.get('step_title')

    params = {}
    if plant_id:
        params['plant_id'] = plant_id
    if step_title:
        params['step_title'] = step_title
    if params:
        return PlantLifeCalendar.objects.filter(**params)
    return PlantLifeCalendar.objects.all()

Чтобы ваш пример работал, вам нужно заменить plant_step_id на plant_step_id__plant_id и step_title на plant_step_id__step_title, потому что это вложенные свойства, которые являются частью PlantStep, а не PlantLifeCalendar.

Однако более простой способ - использовать Django Rest Framework Filtering Guide.

Первая установка pip install django-filter.

...
from django_filters.rest_framework import DjangoFilterBackend

...

class PlantLifeCalendarLinkAPIView(ListAPIView):
    permission_classes = (AllowAnonymous,)
    serializer_class = ReadPlantLifeCalendarSerializer
    queryset = PlantLifeCalendar.objects.all()
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['plant_step_id__plant_id', 'plant_step_id__step_title']

Это означает, что для получения желаемого результата необходимо использовать plant_step_id__plant_id и plant_step_id__step_title в параметрах запроса.

Запись в DRF: https://www.django-rest-framework.org/api-guide/filtering/

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