如何让Django REST查询显示所有字段,含一对一关联表字段
问题描述
我有两个Django模型,CustomUser和UserComputedInfo是一对一关联关系,现在用Django REST Framework创建API,当前只能返回CustomUser的字段,希望同时展示关联的UserComputedInfo的所有字段。
环境:Django v4、Python v3.9、Django REST framework、Windows 10
现有models.py
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
现有serializers.py
from rest_framework import serializers from users.models import CustomUser class CustomUserSerializer(serializers.ModelSerializer): class Meta: fields = ("email", "post_code") model = CustomUser
现有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
解决方案
要在API中同时返回一对一关联的UserComputedInfo字段,有两种简单实现方式:
方法一:嵌套Serializer
先创建UserComputedInfo的序列化器,再在CustomUserSerializer中嵌套它:
修改后的serializers.py:
from rest_framework import serializers from users.models import CustomUser, UserComputedInfo class UserComputedInfoSerializer(serializers.ModelSerializer): class Meta: model = UserComputedInfo fields = "__all__" # 也可指定具体字段,比如("copy_input",) class CustomUserSerializer(serializers.ModelSerializer): # 一对一反向关联默认名称为模型名小写,即usercomputedinfo;若OneToOneField指定了related_name,需替换为对应名称 usercomputedinfo = UserComputedInfoSerializer(read_only=True) class Meta: fields = ("email", "post_code", "usercomputedinfo") model = CustomUser
为避免N+1查询问题,需在视图的queryset中预取关联数据,修改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().select_related('usercomputedinfo') serializer_class = CustomUserSerializer
方法二:直接指定字段来源
若仅需UserComputedInfo中的个别字段,可直接在CustomUserSerializer中通过source指定:
修改后的serializers.py:
from rest_framework import serializers from users.models import CustomUser class CustomUserSerializer(serializers.ModelSerializer): copy_input = serializers.DecimalField(source='usercomputedinfo.copy_input', read_only=True, max_digits=9, decimal_places=6) class Meta: fields = ("email", "post_code", "copy_input") model = CustomUser
同样需在视图的queryset中添加select_related('usercomputedinfo')优化查询性能。
内容的提问来源于stack exchange,提问作者user3848207
相关产品推荐
相关产品推荐

