Django REST接口返回UserProject数据时如何嵌入关联Project模型字段
实现方案
1. 修改序列化器(核心改动)
你需要在UserprojectSerializer中嵌套关联Project的序列化数据,有两种常用实现方式:
方式1:返回完整的Project对象
直接把你已经定义好的ProjectSerializer嵌套进去,会返回Project表的所有字段:
class UserprojectSerializer(serializers.ModelSerializer): # 嵌套Project序列化器,read_only表示只做返回用,不需要传参 project = ProjectSerializer(read_only=True) class Meta: model = Userproject fields = '__all__'
返回结构示例:
{ "id": 17, "created_at": "2021-10-20T16:27:59.938422Z", "updated_at": "2021-10-20T16:27:59.945439Z", "user": 3, "project": { "id":51, "name": "项目名", "descriptor": "项目描述", "created_at": "xxx", "updated_at": "xxx" } }
方式2:自定义字段名,只取Project指定字段
如果你想按你示例里的projectname、projectDescriptor命名单独返回字段,不用嵌套结构,可以这么写:
class UserprojectSerializer(serializers.ModelSerializer): projectname = serializers.CharField(source='project.name', read_only=True) projectDescriptor = serializers.CharField(source='project.descriptor', read_only=True) class Meta: model = Userproject # 记得把新增的字段加到fields里,不用__all__的话就手动列所有要返回的字段 fields = ['id', 'created_at', 'updated_at', 'user', 'project', 'projectname', 'projectDescriptor']
2. 优化现有代码冗余问题
视图层优化
你现在的代码对User表做了两次查询(一次exists、一次get),可以合并成一次查询,同时用select_related提前关联Project表,避免N+1查询性能问题:
class GetUserDataByNameView(APIView): def get(self, request, username): try: # 一次查询拿到用户对象 user = User.objects.get(username=username) # select_related提前查关联的project,减少数据库查询次数 queryset = Userproject.objects.filter(user_id=user.id).select_related('project') readSerializer = UserprojectSerializer(queryset, many=True) return Response(readSerializer.data) except User.DoesNotExist: # 建议这里状态码改成404,更符合REST接口规范,不需要可以保留200 return Response({"status": "error", "data":"no user with this username"}, status=404)
模型层优化
你当前Userproject的__str__方法返回的是数字id,会触发类型错误,需要改成字符串:
def __str__(self): return str(self.id)
其他建议
- 如果不需要自定义返回字段,优先用方式1的嵌套序列化,扩展性更好
- 序列化器里的
ProjectSerializer已经通过ModelSerializer关联了模型字段,不需要手动重复定义name、descriptor字段,除非你要修改默认的校验规则,可以删掉冗余的字段定义。
内容的提问来源于stack exchange,提问作者Nic0lodeon
相关产品推荐
相关产品推荐

