将动态字段添加到Django-rest-framework中的序列化器

时间:2019-01-09 08:00:22

标签: python django rest django-rest-framework

我有一个模特

    class Event(models.Model):
        random_fields...

    class Registrations(models.Model):
        user = models.ForeignKey(User...)
        event = models.ForeignKey(Event...)
        ts = models.DateTimeField(...)

现在,我想获取所有事件的列表以及进行该事件的request用户是否已注册({{1}的ModelSerializer中的is_registered字段也许)。

理想情况下,这应该在单个请求中进行,并且不要Event太多。

有效的方法是什么?

1 个答案:

答案 0 :(得分:1)

我认为您可以使用prefetch related来减少数据库查询。从事件中获取注册时,可以使用prefetch_related一次获取所有注册(因此不需要多个数据库查询)。

因此,首先,您可以这样定义模型:

class Registrations(models.Model):
    user = models.ForeignKey(User...)
    event = models.ForeignKey(Event, related_name="registrations",..)

然后,您可以像这样定义 EventSerializer

class EventSerializer(serializer.ModelSerializer):
    registrations = RegistrationSerializer(many=True, read_only=True)  # <-- getting all registraions via RegistrationSerializer
    is_invited = serializer.SerializerMethodField()

    class Meta:
       model = Event
       fields = "__all__"

    def get_is_invited(self, obj):
        return obj.registrations.filter(user=self.context.get("request").user).exists()  # does not make any DB query

SerializerMethodField已在此处用于获取是否邀请用户。

现在在视图中,调用Event查询集时,请使用prefetch_related

# A minimal example

class SomeView(APIView):
    def get(self, request, **kwargs):
        qset = Event.objects.prefetch_related('registrations').all()
        serializer = EventSerializer(qset, many=True)
        return Response(serializer.data)