0

I try to do hall booking app. I Have set up every things. the model and Serializer view set and urls. Now I want to return from this API 1. All halls with their booking table 2. All user Booking with hall name

I try to SerializerMethodField to get all this data and it is working one side. for example, when I put SerializerMethodField in booking table ti give me the result as will as hall table. But when I try to put in both classes it give Error maximum recursion depth exceeded

Model classes

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()

Serializer


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

View Sets

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()

in Serializer classes when I remove one SerializerMethodField it work. any one have solution

prg.dev
  • 141
  • 1
  • 3
  • 16
  • You need to break the recursion somewhere: in `get_booking`, in `get_hall`, or in both. One option is to pass `context` to serializer indicating that you want to avoid nested `booking` / `hall`, or reduce fields to just `id`. – awesoon Aug 11 '19 at 18:13
  • can you plz explain more – prg.dev Aug 11 '19 at 18:33

1 Answers1

1

You can have a booking SerializerMethodField in your Hall serializer because every booking has a foreign key to Hall, but it doesn't work the other way around (besides being unnecessary). This will cause an infinite recursion, because the serializers keep referencing each other infinitely. You also don't need a SerializerMethodField inside booking to access its hall name because it already has a foreign key to its hall.

Mohammad hp
  • 446
  • 4
  • 16
  • how to access Hall info from booking Serializer ? can you help me :) – prg.dev Aug 11 '19 at 18:41
  • because I want to return Hall info fro each booking ... rather than do get request in front end – prg.dev Aug 11 '19 at 18:46
  • 1
    you don't need to make another get request. just set `depth=1` in your Booking serializer Meta class so it returns the fields of foreign key related objects up to depth 1, instead of just a foreign key value. – Mohammad hp Aug 11 '19 at 18:56
  • it is the depth of information you return to the client. for example lets say x has a foreign key to y, and y has a foreign key to z. setting depth to 1 and getting x will give you x and the fields of y, but only the foreign key to z. setting the depth to 2 will also give you the fields of z. – Mohammad hp Aug 11 '19 at 19:10
  • good... thank you ... let say that x has a foreign key to y and z and I want only to return one of the foreign key let say {y} how i do it ? – prg.dev Aug 11 '19 at 19:23
  • Unfortunately depth is applicable to the whole serializer, the only way to achieve this is creating two different serializers – Mohammad hp Aug 11 '19 at 19:38
  • Also, I notes that when i try to get hall tit return to me at booing the hall info. it duplicate it self.... do you have any solution to this problem – prg.dev Aug 11 '19 at 19:38
  • The booking serializer shouldnt contain a hall field – Mohammad hp Aug 11 '19 at 19:55
  • I have one more question if don't mind ..... when I try to POST new booking it give me Error that say ```IntegrityError NOT NULL constraint failed: api_bookingmodel.hall_id ``` did you know how to solve it – prg.dev Aug 11 '19 at 20:06
  • https://stackoverflow.com/questions/25964312/not-null-constraint-failed-after-adding-to-models-py there is a question related to this error here – Mohammad hp Aug 11 '19 at 20:30
  • the problem is the hall id is not save ... when i try the stackoverflow.com/questions/25964312/… ..... it save to db hall = null – prg.dev Aug 14 '19 at 12:42