【问题标题】: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__"
    

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

【问题讨论】:

    标签: python python-3.x django django-rest-framework django-queryset


    【解决方案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)
      

      【讨论】:

        猜你喜欢
        • 2021-03-10
        • 2014-09-20
        • 1970-01-01
        • 1970-01-01
        • 2011-12-24
        • 2017-11-15
        • 2017-06-24
        • 2021-01-13
        • 2013-02-22
        相关资源
        最近更新 更多