Ruben Adriaanse
Ruben Adriaanse

Reputation: 83

Is there a way to grab specific "fields" from request.data sent to the Django REST framework API in a POST method

I've got a Project model, with a project_code field. When the API receives a POST request, the request.data will also contain a project_code. I then want to filter my Project model objects based on the project_code inside the request.data

Once I've linked to request.data project_code to the Project model's project_code field, I want to save my Ticket model object to the database. Inside my Ticket model, there is a field called project which is related with a ForeignKey to the Project model.

Thus in essence the project_code inside the POST request.data needs to be used in order to save my Ticket model to the database with the correct Project model foreign Key.

Here are my models:

from django.db import models

class Project(models.Model):
    
    project_code = models.TextField(blank=True)
    project_description = models.TextField(blank=True)

    def __str__(self):
        return self.project_code

class Ticket(models.Model):

    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    ticket_url = models.TextField(blank=True)
    time_submitted = models.DateField(blank=True, auto_now_add=True)
    description = models.TextField(blank=True)
    user = models.TextField(blank=True)
    type = models.TextField(blank=True)

    def __str__(self):
        return self.description

Here are my serializers:

from rest_framework import serializers
from ticketing_app_api.models import Ticket, Project

class TicketSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ticket
        fields = ['id', 'ticket_url', 'description', 'user', 'type']

And here are my views:

from ticketing_app_api.models import Ticket
from ticketing_app_api.serializers import TicketSerializer
from rest_framework import generics
from rest_framework.decorators import api_view
from rest_framework.response import Response
# from rest_framework.reverse import reverse
from rest_framework import status


@api_view(['GET', 'POST'])
def ticket_list(request):
    """
    List all tickets, or creates a new ticket.
    """
    if request.method == 'GET':
        tickets = Ticket.objects.all()
        serializer = TicketSerializer(tickets, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = TicketSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class TicketDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Ticket.objects.all()
    serializer_class = TicketSerializer

Upvotes: 0

Views: 1162

Answers (1)

nicootto
nicootto

Reputation: 159

The cleaner approach would be to get the project_id when you create the project, and then just send it when creating the ticket. In this case, your TicketSerializer must also contain the project:

class TicketSerializer(serializers.ModelSerializer):

    class Meta:
        model = Ticket
        fields = ["id", "ticket_url", "description", "user", "type", "project"]

and when you send the post request, you have to specify which is the project:

{
    "ticket_url": "http://ticket.com",
    "project": 1
}

In case you must use the project_code, you can set the project when validating the data:

class TicketSerializer(serializers.ModelSerializer):

    class Meta:
        model = Ticket
        fields = ["id", "ticket_url", "description", "user", "type"]

    def validate(self, attrs):
        attrs["project"] = Project.objects.get(
            project_code=self.initial_data.get("project_code")
        )
        return attrs

Upvotes: 1

Related Questions