crokadilekyle
crokadilekyle

Reputation: 100

JSON data not being sent - Django Rest Framework / React

So, I'm new to Django and after hours of searching / trying different things I can't figure this out.

I have a form that submits my components state to the api, adds the values to the database, and then displays them in a table. Everything is getting into the database except for the "projects" field. When I look in the React Dev tools, the value I expect is in my state.

project: 3

But after I submit the form the returned value shows as null.

project: null

I'm really not sure why the value is null.

Here is my models.py

class Completed(models.Model):
    completed = models.BooleanField(default=False)
    url = models.CharField(max_length=100)
    handle = models.CharField(max_length=30)
    filename = models.CharField(max_length=100)
    size = models.IntegerField()
    source = models.CharField(max_length=50)
    uploadId = models.CharField(max_length=50)
    originalPath = models.CharField(max_length=50)
    owner = models.ForeignKey(
        User, related_name="completed", on_delete=models.CASCADE, null=True)
    project = models.ForeignKey(
        Project, related_name="projectId", on_delete=models.CASCADE, null=True)
    uploadDate = models.DateTimeField(auto_now_add=True)

Here is the Project model

class Project(models.Model):
    projectCode = models.CharField(max_length=10)
    projectName = models.CharField(max_length=100)
    user = models.ForeignKey(
        User, related_name="projects", on_delete=models.CASCADE, null=True)
    editor = models.ForeignKey(
        User, on_delete=models.CASCADE, null=True)
    creationDate = models.DateTimeField(auto_now_add=True)
    completedDate = models.DateTimeField(null=True, blank=True)
    dueDate = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return f"{self.projectName}"

Here are the serializers

# Project Serializer


class ProjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = Project
        fields = [
            'id',
            'projectCode',
            'projectName',
            'user'
        ]
        depth = 1

# Completed Serializer


class CompletedSerializer(serializers.ModelSerializer):
    # project = ProjectSerializer()

    class Meta:
        model = Completed
        fields = [
            'completed',
            'url',
            'handle',
            'filename',
            'size',
            'source',
            'uploadId',
            'originalPath',
            'owner',
            'project',
            'uploadDate'
        ]
        depth = 1

I tried adding the ProjectSerializer into the CompletedSerializer but it gave me a 400 bad-request error.

And here is the viewset

class CompletedViewSet(viewsets.ModelViewSet):
    permission_classes = [
        permissions.IsAuthenticated
    ]

    serializer_class = CompletedSerializer

    def get_queryset(self):
        queryset = self.request.user.completed.all().filter(completed=True)
        return queryset

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

Can anyone tell me what I'm doing wrong here?

Upvotes: 0

Views: 171

Answers (1)

Fran
Fran

Reputation: 899

You're using depth=1 on your serializers. That means you'll have nested serializer for your ForeignKey. By default, nested serializers are read-only. If you want a writable nested serializer, you have to uncomment your # project = ProjectSerializer() on CompletedSerializer and pass all the data for the creation of a project instance. I don't think this is what you want. If I've understood well, you only want to reference an existing project. So, the best way to accomplish that, in my opinion, is removing the depth on your CompletedSerializer. If you need the project when you list or retrieve a Completed instance, go with a different serializer based on the request action. Here more details about writable-nested serializers https://www.django-rest-framework.org/community/3.0-announcement/#writable-nested-serialization.

For using different serializers, this is a reference. Add this code in your ViewSet:

    def get_serializer_class(self):
        if self.action == 'list' or self.action == 'retrieve':
            return CompletedNestedSerializer
        return CompletedSerializer

Upvotes: 1

Related Questions