首页 > 解决方案 > Django REST,一个 GET 中的多个查询集

问题描述

我有以下两个模型:

模型.py:

from django.contrib.auth.models import User

# Create your models here.
class Project(models.Model):

    id = models.AutoField(db_column = 'db_ID', primary_key = True)
    name = models.CharField(max_length=500, default = None)
    descriptor = models.CharField(max_length = 1000, null = True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'projects'

    def __str__(self):
        return self.name




class Userproject(models.Model):
    id = models.AutoField(db_column = 'db_ID', primary_key = True)
    user = models.ForeignKey(User, on_delete= models.SET_NULL, null = True)
    project = models.ForeignKey('Project', on_delete = models.SET_NULL, null = True)
    created_at = models.DateTimeField(auto_now_add=True, null=True)
    updated_at = models.DateTimeField(auto_now=True, null = True)

    class Meta:
        db_table = 'UserProjects'
    def __str__(self):
        return self.id

Userprojects 'user' 和 'project' 字段指向上面的 Usermodel 和 Projectmodel。

现在我有这样的看法:

class GetUserDataByNameView(
    APIView,
):
    def get(self, request, username):
        if User.objects.filter(username = username).exists():
            uid = User.objects.get(username = username).id
            queryset = Userproject.objects.filter(user_id = uid)
            readSerializer = GetUserDataSerializer(queryset, many = True)
            return Response(readSerializer.data)
        else:
            return Response({"status": "error", "data":"no user with this username"}, status = 200)

和这个序列化程序

from rest_framework import serializers

from .models import Project
from .models import Userproject

class ProjectSerializer(serializers.ModelSerializer):
    name = serializers.CharField(max_length = 500, required = True)
    descriptor = serializers.CharField(max_length = 1000,  default = None)

    class Meta:
        model = Project
        fields = ['name','descriptor',]


class UserprojectSerializer(serializers.ModelSerializer):
    class Meta:
        model = Userproject
        fields = '__all__'

因此,当前端通过 url 中的用户名时,我会发回这个 JSON:

[
    {
        "id": 16,
        "created_at": "2021-10-20T16:05:03.757807Z",
        "updated_at": "2021-10-20T16:05:03.762307Z",
        "user": 3,
        "project": 50
    },
    {
        "id": 17,
        "created_at": "2021-10-20T16:27:59.938422Z",
        "updated_at": "2021-10-20T16:27:59.945439Z",
        "user": 3,
        "project": 51
    }
]

我需要在这个查询集中包含对 Project 模型的引用,我听说我需要一个 Serializer 方法。但是尝试这个序列化程序不起作用并给我一个属性错误

class GetUserDataSerializer(serializers.ModelSerializer):

    projects = serializers.SerializerMethodField()

    class Meta:
        model = Userproject
        fields = '__all__'

    def get_projects(self, obj):
        data = ProjectSerializer(obj.Project.all(), many = True).data
        return data

错误如下:

'Userproject' object has no attribute 'Project'

我想要实现的是包含具有给定项目 ID 的项目模型(在 json 中称为项目),例如:

{
        "id": 17,
        "created_at": "2021-10-20T16:27:59.938422Z",
        "updated_at": "2021-10-20T16:27:59.945439Z",
        "user": 3,
        "project": 51
        {
         projectname : ...
         projectdescriptor: ...
        }
    }

标签: djangoapirest

解决方案


我不确定我是否正确地回答了您的问题,但以下内容应该让您走上正确的道路。

从您的视图或您调用 UserProfile 的任何地方,您应该这样做,

#provided username is unique in your models.
class GetUserDataByNameView(
    APIView,
):
    def get(self, request, username):
        try:
            uid = User.objects.only('id').get(username=username)
        except User.DoesNotExist:
            return Response({"status": "error", "data":"no user with this username"}, status = 200)

         queryset = Userproject.objects.select_related('project').filter(user_id=uid.id)
         readSerializer = GetUserDataSerializer(queryset, many = True)
         return Response(readSerializer.data)

然后在你的序列化程序中,你应该这样做,

class GetUserDataSerializer(serializers.ModelSerializer):

    projects = serializers.SerializerMethodField(source='get_projects')

    class Meta:
        model = Userproject
        fields = '__all__'

    def get_projects(self, obj):
        serial_proj = ProjectSerializer(obj.project)
        return serial_proj.data

推荐阅读