Search code examples
pythondjangodjango-rest-frameworkdjango-querysetdjango-serializer

How to get this Django REST query to display all fields, including fields from related one-to-one table


This is my Django models.py with 2 tables having a one-to-one table relationship. UserComputedInfo model has a one-to-one relationship with CustomUser model.

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.contrib.auth import get_user_model


class CustomUser(AbstractUser):
    email = models.EmailField(unique=True)
    post_code = models.DecimalField(max_digits=9, decimal_places=6)

    def __str__(self):
        return self.username


class UserComputedInfo(models.Model):
    user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE)
    copy_input = models.DecimalField(max_digits=9, decimal_places=6)

    def __str__(self):
        return self.copy_input

I am trying to create a REST API to display all the fields in the 2 tables. I am using Django REST framework.

This is my serializers.py

from rest_framework import serializers
from users.models import CustomUser


class CustomUserSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ("email", "post_code")
        model = CustomUser

This is my views.py

from rest_framework import generics

from django.contrib.auth import get_user_model
from .serializers import CustomUserSerializer


class PostCodeAPIView(generics.ListAPIView):
    queryset = get_user_model().objects.all()
    serializer_class = CustomUserSerializer

The API will display all the fields in CustomUser table. However, I want to display all the fields in the related one-to-one UserComputedInfo table as well.

I am using Django v4, python v3.9, Django REST framework on Windows 10.


Solution

  • I will answer my own question. It has been tested to work successfully.

    # serializers.py
    from rest_framework import serializers
    from users.models import CustomUser
    
    
    class CustomUserSerializer(serializers.ModelSerializer):
    
        class Meta:
            fields = ("email", "post_code", "usercomputedinfo")
            model = CustomUser
            depth = 1  # display all the fields in related 1-to-1 table 
    

    In https://www.django-rest-framework.org/api-guide/serializers/#modelserializer, it is stated that the ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields.

    The field usercomputedinfo corresponds to the one-to-one table UserComputedInfo. Take special note that the naming of the field follows a convention used by ModelSerializer. In this case, it has to be all lowercase. If you use UserComputedInfo as the field, it won't work. I cannot find the documentation on the field naming convention used by ModelSerializer. depth = 1 is needed to generate nested representations.

    Instead of displaying all the fields, sometimes we want to specify specific fields. This is the code for doing it.

    from rest_framework import serializers
    from users.models import CustomUser, UserComputedInfo
    
    
    class UserComputedInfoSerializer(serializers.ModelSerializer):
        class Meta:
            model = UserComputedInfo
            fields = ("copy_input")
    
    
    class CustomUserSerializer(serializers.ModelSerializer):
        usercomputedinfo = UserComputedInfoSerializer()
    
        class Meta:
            fields = ("email", "postal_code", "usercomputedinfo")
            model = CustomUser