Структура Django Rest — Получение первичного ключа в теле ответа после

#python #django #django-models #django-rest-framework #django-views

Вопрос:

Я пытаюсь создать rest api с помощью Django Restframework. В этом Api я использую модель под названием Event .

models.py

 class Event(models.Model):
    key = models.IntegerField(auto_created=True, primary_key=True)
    start_date = models.DateTimeField()
    end_date = models.DateTimeField()
    subject = models.TextField(max_length=250)
    description = models.TextField(max_length=2500)
    created = models.DateTimeField(default=django.utils.timezone.now)
    host = models.ForeignKey('auth.User', related_name='host', on_delete=models.CASCADE, null=True)
 

serializers.py

 class EventSerializer(serializers.HyperlinkedModelSerializer):
    host = serializers.StringRelatedField()
    key = serializers.IntegerField(read_only=True)

    class Meta:
        model = Event
        fields = ['url', 'key', 'start_date', 'end_date', 'subject', 'description', 'host']
 

views.py

 class EventViewSet(viewsets.ModelViewSet):
    queryset = Event.objects.all()
    serializer_class = EventSerializer

    @action(detail=True)
    def skills(self, request, *args, **kwargs):
        return get_key_values(TblClsOne=EventSkills, TblClsTwo=Skills, table_one_column_name="event_id",
                              table_one_fk_name='skill_id', table_two_column_name="skill_id",
                              table_one_filter_value=kwargs["pk"])


    def perform_create(self, serializer):
        serializer.save(host=self.request.user)
 

Когда я хочу узнать подробности о событии, я звоню GET /events/<id>/

ПОЛУЧИТЬ /события/502/ Пример

 {
    "url": "http://127.0.0.1:8000/events/502/",
    "key": 502,
    "start_date": "2021-09-23T20:00:00Z",
    "end_date": "2021-09-23T21:00:00Z",
    ...
    "host": null
}
 

Но если я создам новое событие с помощью POST /events/

Я получу пустые поля для key и url .

Как я могу интегрировать созданные значения для этих двух полей? Они обязательны для перехода к подробному представлению.

Ответ №1:

Один из способов решить эту проблему-вернуть объект из perform_create , переопределить create и снова использовать созданный объект в сериализаторе, как это:

 class EventViewSet(viewsets.ModelViewSet):
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        obj = self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(self.get_serializer(obj).data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        return serializer.save(host=self.request.user)
 

Ответ №2:

Вы можете создать новый сериализатор событий для использования в методе create, который не устанавливает ключ как read_only, и использовать его для метода create. Переопределите класс get_serializer_класс в вашем представлении, чтобы выбрать правильный сериализатор в зависимости от случая.

 def get_serializer_class(self):
    if self.action != "skills":
        return CreateEventSerializer
    return super().get_serializer_class()
 

Что касается URL-адреса, я предполагаю, что вы не получите его обратно, потому что это не поле модели. Я надеюсь, что это немного поможет.

Комментарии:

1. спасибо за ваше вдохновение. К сожалению, я не получу ключ в теле ответа POST /event/ . У вас есть какие-нибудь идеи, как это может сработать?