Home > Net >  Django Rest Framework - Receive Primary Key in POST Response body
Django Rest Framework - Receive Primary Key in POST Response body

Time:09-27

I try to build a rest api with Django Restframework. In this Api i use a Model called 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)

When I want to see the Details from a event i call GET /events/<id>/

GET /events/502/ Example

{
    "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
}

But if I create a new Event via POST /events/

I will receive empty fields for keyand url.

How can I integrate the created values for these two fields? They are mandatory for navigating to the detail view.

CodePudding user response:

You can create a new event serializer to use for the create method that doesnt set the key as read_only and use it for the create method. Overide the get_serializer_class in your view to select the correct serializer depending on the case.

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

As for the url I am guessing you are not getting it back because it is not a model field. I hope this helps a bit.

CodePudding user response:

One way to solve this is to return the object from perform_create, and override create and use the created object on the serializer again like this:

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)
  • Related