Django not saving data with post

Question:

I have this view:

class TaskApiView(APIView):
    def post(self, request):
        serializer = TaskSerializer(data=request.data)
        print(request.data)
        if serializer.is_valid():
            print("valid", serializer.data)
            serializer.save()
            return Response(status=status.HTTP_201_CREATED)
        else:
            print(serializer.errors)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

request body:

{
    "content": "asd"
}

log:

{'content': 'asd'}
valid {'id': 30}
[21/Oct/2023 11:33:19] "POST /api/task/create HTTP/1.1" 201 0

But when I try to get all tasks with this view

class TaskListAPIView(generics.ListAPIView):
    queryset = Task.objects.all()
    serializer_class = TaskSerializer

I get just the id:

[
    {
        "id": 25
    }
]

Serializer:

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = "__all__"

Model

    id: models.UUIDField(unique=True, auto_created=True)
    content: models.CharField(default="")
    creationDate: models.DateField(auto_now_add=True)
    author: models.ForeignKey(User, on_delete=models.CASCADE)
    status: models.CharField(
        choices=StatusEnum,
        max_length=5,
        default=StatusEnum.TODO,
    )

    def __str__(self):
        return self.id + self.content

settings.py:

REST_FRAMEWORK = {
    "DEFAULT_PARSER_CLASSES": [
        "rest_framework.parsers.JSONParser",
    ]
}

I want to create a task with content

Asked By: Alex Ironside

||

Answers:

Well that’s because your model only has an id field. Indeed, you define fields as attributes, not as annotations, so:

class Task(models.Model):
    id = models.UUIDField(unique=True, auto_created=True)
    content = models.CharField(default='')
    creationDate = models.DateField(auto_now_add=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    status = models.CharField(
        choices=StatusEnum, max_length=5, default=StatusEnum.TODO
    )

    def __str__(self):
        return f'{self.id} {self.content}'

You will need to make a migration and migrate to migrate it properly. Likely injecting defaults for already existing models.

With the given data you provide, the serializer will however reject the data: you don’t specify a value for the author.

Answered By: Willem Van Onsem