【问题标题】:Serializer Method Field: Error maximum recursion depth exceeded序列化程序方法字段:超出错误最大递归深度
【发布时间】:2019-12-18 09:36:04
【问题描述】:

我尝试做大厅预订应用程序。我已经设置了所有东西。模型和序列化器视图集和 url。现在我想从这个 API 返回 1. 所有大厅都有他们的预订表 2. 所有用户都用大厅名称预订

我尝试使用 SerializerMethodField 来获取所有这些数据,并且它在一边工作。例如,当我将 SerializerMethodField 放在预订表中时,我会像大厅表一样给我结果。但是当我尝试同时放入这两个类时,它会给出错误maximum recursion depth exceeded

模型类

class HallModel(models.Model):

    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='hall_owner')
    name = models.CharField(max_length=100)
    price = models.FloatField()
    phone = models.CharField(max_length=9, blank=True)
    size = models.CharField(max_length=50)
    region = models.CharField(max_length=100)
    state = models.CharField(max_length=100)
    image_1 = models.ImageField(upload_to='halls_image')
    image_2 = models.ImageField(upload_to='halls_image')
    image_3 = models.ImageField(upload_to='halls_image')
    created_at = models.DateTimeField(auto_now_add=True)



class BookingModel(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_booking')
    hall = models.ForeignKey(HallModel, on_delete=models.CASCADE, related_name='hall_owner')

    time_date = models.DateTimeField(auto_now_add=True)
    booking_method = models.IntegerField()

序列化器


class HallSerializer(serializers.ModelSerializer):
    booking = serializers.SerializerMethodField()

    class Meta:
        model = HallModel
        fields = '__all__'

    def get_booking(self, obj):
        booking = BookingSerializer(obj.hall_owner.all(),many=True).data
        return booking


    def perform_create(self, serializer):
        serializer.save()


class BookingSerializer(serializers.ModelSerializer):
    hall = serializers.SerializerMethodField()

    class Meta:
        model = BookingModel
        fields = '__all__'

    def get_hall(self, obj):
        serializer_data = HallSerializer(obj.hall).data
        return serializer_data

视图集

class HallViewSet(viewsets.ModelViewSet):
    queryset = HallModel.objects.all()
    serializer_class = HallSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)



class BookingViewSet(viewsets.ModelViewSet):

    serializer_class = BookingSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    def get_queryset(self):
        return self.request.user.user_booking.all()

当我删除一个 SerializerMethodField 时,在 Serializer 类中它可以工作。任何人都有解决方案

【问题讨论】:

  • 您需要在某处中断递归:在get_bookingget_hall 或两者中。一种选择是将context 传递给序列化程序,表明您希望避免嵌套booking / hall,或者将字段减少到仅id
  • 你能解释一下吗

标签: django django-models django-rest-framework django-forms django-views


【解决方案1】:

您可以在 Hall 序列化程序中设置一个预订 SerializerMethodField,因为每个预订都有一个 Hall 的外键,但反过来就不行(除了不必要之外)。这将导致无限递归,因为序列化程序会无限地相互引用。您也不需要在预订中使用 SerializerMethodField 来访问其大厅名称,因为它已经有一个指向其大厅的外键。

【讨论】:

  • 如何通过预订序列化程序访问大厅信息?你能帮帮我吗:)
  • 因为我想为每次预订返回大厅信息......而不是在前端获取请求
  • 您不需要再提出一个获取请求。只需在您的 Booking 序列化程序 Meta 类中设置 depth=1,以便它返回深度为 1 的外键相关对象的字段,而不仅仅是外键值。
  • 这是您返回给客户的信息深度。例如,假设 x 对 y 有一个外键,而 y 对 z 有一个外键。将深度设置为 1 并获取 x 将为您提供 x 和 y 的字段,但只有 z 的外键。将深度设置为 2 也会为您提供 z 的字段。
  • 好...谢谢...假设 x 有一个指向 y 和 z 的外键,我只想返回一个外键让我们说 {y} 我是怎么做到的?
最近更新 更多