德扬戈。如何向查询结果中添加字段?

2024-05-15 01:35:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个房间模型,我想将is_member布尔字段添加到带有房间的查询集。你怎么能做到这一点?我曾想过使用.annotate (),但这对我的任务不起作用

型号.py

from django.db import models

class Room(models.Model):
    name = models.CharField(max_length=150)
    members = models.ManyToManyField(User, blank=True)

视图.py

from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import RoomSerializer
from .models import Room

class RoomView(APIView):
    def get(self, request):
        rooms = Room.objects.all() # get all rooms
        user = request.user # get current user

        for room in rooms:
            members = room.members.all() # get members
            is_member = user in members # set boolean value
            room.is_member = is_member # set in room

        serializer = RoomSerializer(rooms, many=True)
        return Response(serializer.data)

序列化程序.py

from rest_framework import serializers
from .models import Room

class RoomSerializer(serializers.ModelSerializer)
    is_member = serializers.BooleanField(read_only=True)
    
    class Meta:
        model = Room
        fields = "__all__"
    

我用这种方式解决了这个问题,但还有其他选择吗? 请帮帮我


Tags: frompyimportgetismodelsallclass
2条回答

当您使用这样的M2M时,您可以使用自己的直通模型,而不是让django自动完成

这使您能够将自己的字段添加到关系、属性或自定义manager/queryset

这方面的文件在这里https://docs.djangoproject.com/en/3.1/topics/db/models/#extra-fields-on-many-to-many-relationships

因此,通过查询through模型,可以确定用户是否是给定房间的成员

自定义直通模型方法的一个非常粗略的示例


class Room(models.Model):
    users = models.ManyToManyField("User", through=ThroughModel)

class User(models.Model):
    text = models.TextField()

class ThroughModel(models.Model):
    room_id = models.ForeignKey(Room)
    user_id = models.ForeignKey(User)
    is_member = models.BooleanField()

# this will return a list of ThroughModel objects
ThroughModel.objects.filter(user=instance_of_user, is_member=True)

# this will return a list of A objects based on an extra field on the through table
Room.objects.filter(users__ThroughModel__is_member=True)

# keep in mind that limiting by one of the foreign keys on the through model is easier
Room.objects.filter(users=instance_of_user)

你能试试这个吗。这不会在queryset中添加is_成员,但我认为您正在寻找类似的内容

#  Serializer
class RoomSerializer(serializers.ModelSerializer):
    is_member = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = Room
        fields = "__all__"

    def get_is_member(self, obj):
        user = self.context["request"].user
        if user in obj.members.all():
            return True
        return False

#  View
class RoomView(APIView):
    def get(self, request):
        rooms = Room.objects.prefetch_related("members").all()  # get all rooms
        serializer = RoomSerializer(rooms, context={"request": request}, many=True)
        return Response(serializer.data)

你应该得到想要的回应

[
    {
        "id": 1,
        "is_member": true,
        "name": "first",
        "members": [
            1
        ]
    },
    {
        "id": 2,
        "is_member": true,
        "name": "second",
        "members": [
            1,
            2
        ]
    }
]

相关问题 更多 >

    热门问题