Search code examples
pythondjangodjango-rest-framework

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?


Solution

  • 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}}