Django Rest Framework - Получение первичного ключа в теле POST-ответа

Я пытаюсь создать 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>/

GET /events/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/

я получу пустые поля für key и url.

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

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

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

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

Один из способов решения этой проблемы - вернуть объект из 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)
Вернуться на верх