Django User as foreignKey has strange behaviour
I am building a restful API in Django and I have noticed something quite odd! This is my Topic Model:
class Topic(models.Model):
""" Topic base model"""
owner = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=150, blank=False, null=False)
content = models.CharField(max_length=500, blank=False, null=False)
date_added = models.DateTimeField(auto_now_add=True, editable=False)
def __str__(self):
return self.title
And this is my serializer:
class TopicSerializer(serializers.ModelSerializer):
"""Serializer for the Topic model"""
user = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Topic
exclude = ['owner']
extra_kwargs = {'pk': {'read_only': True}, 'owner': {'read_only': True}}
As you can see owner is excluded, but when I make a get request /api/topics/1/ at my Topic ModelViewSet, I get:
{"id":1,"user":"Javad","title":"a","content":"b","date_added":"2024-08-25T19:57:00.712475Z"}
And when I include owner in my serializer I get:
{"id":1,"user":"Javad","title":"a","content":"b","date_added":"2024-08-25T19:57:00.712475Z","owner":"90f8d3d9-08c2-4890-9ba6-3e6f912b10ee"}
So why exactly does Django add a "user" field to my model?
I guess this must be intentional and unique to user Model, right? Can I control this?
So why exactly does Django add a "user" field to my model?
Because you ask the serializer to do that. You defined a:
user = serializers.ReadOnlyField(source='owner.username')
You can remove this with:
class TopicSerializer(serializers.ModelSerializer):
# 🖟 remove
# user = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Topic
exclude = ['owner']
extra_kwargs = {'pk': {'read_only': True}, 'owner': {'read_only': True}}
If you want the field to user the username, you work with:
class TopicSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Topic
exclude = ['owner']
extra_kwargs = {'pk': {'read_only': True}, 'owner': {'read_only': True}}