Django扩展User模型后如何同时序列化User与UserExtended的字段
两次报错的核心原因是你绑定的模型只包含一半需要的字段,DRF不会自动识别跨模型关联字段,需要手动声明。你通过OneToOneField扩展User模型的场景,直接在序列化器中显式声明关联字段即可,无需拆分多个序列化器,具体修改如下:
1. 调整序列化器配置
修改serializers.py中的UserSerializer,显式关联UserExtended模型的crm_guid字段:
# Django imports from django.contrib.auth.models import User from users.models import UserExtended from django.contrib.auth.hashers import make_password # Third party imports from rest_framework import serializers class UserSerializer(serializers.ModelSerializer): # 新增guid字段,通过反向关联指向UserExtended的crm_guid # 如果定义OneToOneField时指定了related_name,将source中的userextended替换为你设置的别名 guid = serializers.UUIDField(source='userextended.crm_guid', read_only=True) class Meta: model = User fields = ['id', 'last_login', 'first_name', 'last_name', 'username', 'email', 'is_active', 'guid'] # 如果需要支持写入guid等扩展字段,重写create方法处理关联模型创建 def create(self, validated_data): extended_data = validated_data.pop('userextended', {}) user = User.objects.create(**validated_data) UserExtended.objects.create(user=user, **extended_data) return user # 支持更新扩展字段的话重写update方法 def update(self, instance, validated_data): extended_data = validated_data.pop('userextended', {}) # 更新User原生字段 for attr, value in validated_data.items(): setattr(instance, attr, value) instance.save() # 更新扩展字段 for attr, value in extended_data.items(): setattr(instance.userextended, attr, value) instance.userextended.save() return instance
2. 优化视图查询避免N+1问题
修改views.py中的查询逻辑,使用select_related预加载关联的UserExtended数据,减少数据库查询次数:
# Django imports from django.contrib.auth.models import User # Third party imports from rest_framework import generics from rest_framework.permissions import IsAdminUser # App imports from users.serializers import UserSerializer class UsersListCreateView(generics.ListCreateAPIView): permission_classes = [IsAdminUser] serializer_class = UserSerializer def get_queryset(self): # 新增select_related预加载扩展表数据 queryset = User.objects.all().select_related('userextended') email = self.request.query_params.get('email') username = self.request.query_params.get('username') if email: queryset = queryset.filter(email=email) if username: queryset = queryset.filter(username=username) return queryset class UserRetrieveUpdateDeleteView(generics.RetrieveUpdateDestroyAPIView): permission_classes = [IsAdminUser] # 新增select_related预加载扩展表数据 queryset = User.objects.all().select_related('userextended') serializer_class = UserSerializer
内容的提问来源于stack exchange,提问作者strumpy_strudel
相关产品推荐
相关产品推荐

