Background
As of Django Rest Framework 3.14.0 (I'm using it right now), it would seem that none of the solutions provided above work. (Maybe romor's, but this response goes into much more details, IMO)
Input
I have a BaseModel that has Meta property "abstract" set to True.
Then I'm creating a serializer for my non-base model.
Some sample code — Base Class:
# _base.py
from uuid import uuid4
from django.db import models
class BaseModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
created_at = models.DateTimeField(auto_now_add=True...)
updated_at = models.DateTimeField(auto_now=True...)
class Meta:
abstract = True
Model I'm making a serializer for:
from django.db import models
from ._base import BaseModel
class Comment(BaseModel):
file = models.FileField(...)
text = models.TextField(...)
author = models.ForeignKey("accounts.BaseUser"...)
class Meta:
verbose_name = _("Comment")
verbose_name_plural = _("Comments")
ordering = ["-created_at"]
As you can see, I have a field called id
, an instance of UUIDField class.
Using a read-only field results in that id
field being omitted from the response, even though it's present in the Model definition. I've tried this field as an option of UUIDField, and using ReadOnlyField directly.
Solution
To fix this, I've created a serializer ModelWithUUID
, it looks something like this:
from rest_framework import serializers
class ModelWithUUID(serializers.ModelSerializer):
id = serializers.UUIDField()
So, in a way, this is what romor and Jann (the editor) suggested in their response.
By doing this, my final serializer is pretty simple, and looks like this:
class CommentSerializer(ModelWithUUID):
author = AdditionalSerializerForAuthor() # Not the actual name
file = FileRepresentationField(allow_null=True) # I need some "weird" conversions, don't judge me
class Meta:
model = Comment
fields = "__all__"
This allows me to use __all__
for fields and have an id
field at all times.
Additional background, that you may need to know to understand why I do things this way (you can skip this)
It should be noted that I use Django 5.0.1 and drf_yasg.
Maybe my approach is wrong, but I use the serializer's .data
property as data for response. And to be even more specific — I use a
combination of 3 serializers for all (or almost all) of my endpoints:
- Input Serialzier, that is used as a type hint for drf_yasg;
- Output Serializer, same (CommentSerializer is a part of one);
- Internal Seraializer, that takes data from Input Serializer, and returns an Output Serializer, or a Validation Error.
This combination seems to be pretty flexible so far, but it may not be the best practice in the long run.
pk = serializers.Field()
, but it should beid = serializers.Field()
. I oversaw that typo. – Nabob