姜戈。如何在查询结果中添加字段?

Posted

技术标签:

【中文标题】姜戈。如何在查询结果中添加字段?【英文标题】:Django. How do I add a field to a query result? 【发布时间】:2021-03-14 05:48:38 【问题描述】:

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

models.py

from django.db import models

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

views.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)

serializers.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__"
    

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

【问题讨论】:

【参考方案1】:

你可以试试这个。这不会在查询集中添加 is_member 但我认为您正在寻找类似的东西。

#  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
        ]
    
]

【讨论】:

【参考方案2】:

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

这使您能够将自己的字段添加到关系、属性或自定义管理器/查询集。

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

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

通过模型方法自定义的非常粗略的示例;


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)

【讨论】:

以上是关于姜戈。如何在查询结果中添加字段?的主要内容,如果未能解决你的问题,请参考以下文章

空查询返回数据库中的所有字段。姜戈

Laravel如何在查询结果中添加新字段

姜戈。如何在布尔表单字段上应用 css 样式?

姜戈。数据库查询:一个字段不同

如何将字段添加到 Access 2003 查询以显示基于另一个字段的结果?

如何在mysql 的查询结果中增加一个字段进去