Edgar Albarracin
Edgar Albarracin

Reputation: 93

Save master and details in DRF with foreign key

I am trying to save a entity from a request.

I have two models

class Reservation(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    userReservation = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
    dateStart = models.DateTimeField(null=False, blank=False, default=datetime.now)  

    def __str__(self):
        return str(self.id)


class DetailsReservation(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    Reservation = models.ForeignKey(Reservation, blank=False, on_delete=models.CASCADE, null=True, related_name='reservation_details')
    product = models.ForeignKey(Product, blank=False, on_delete=models.CASCADE, null=True, related_name='products_reservation')
    Quantity = models.IntegerField(null=False, blank=False, default=0)

    def __str__(self):
        return self.product.product_Description +" by: " + self.userbyReserva.email

    def save(self, *args, **kwargs):
        self.userbyReserva = self.Reservation.userReservation
        super(DetailsReservation, self).save(args, kwargs)

Then i have two serializers

class DetailsReservationSerializer(serializers.ModelSerializer):
    class Meta:
        model = DetailsReservation
        fields = '__all__'


class ReservationSerializer(serializers.ModelSerializer):
    reservation_details = DetailsReservationSerializer(many=True)
    class Meta:
        model = Reservation
        fields = '__all__'

then in my views, i have

class makereservation(generics.ListCreateAPIView):

    def post(self, request, *args, **kwargs):
        data = request.data
        data["userReservation"] = request. user.id
        serializer = ReservationSerializer(data=data)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return Response(status=status.HTTP_201_CREATED)
    return Response(status=status.HTTP_400_BAD_REQUEST)

I am trying with postman (for emulate request type post)

this is my json

{
    "dateStart": "2020-09-20T13:00:00-05:00",
    "reservation_details": [{
            "product": 1,
            "Quantity": 2
        },
        {
            "productId": 2,
            "Quantity": 2
        }, {
            "productId": 3,
            "Quantity": 1
        }
    ]
}

but i don't know, how save this.

Upvotes: 1

Views: 674

Answers (1)

Henry Woody
Henry Woody

Reputation: 15662

Django Rest Framework does not have built-in support for creating nested objects. However they do provide some documentation for adding this functionality here: http://www.django-rest-framework.org/api-guide/serializers/#dealing-with-nested-objects

You'll have to add creation functionality for the DetailsReservation within the ReservationSerializer's create method after creating the Reservation object.

Here's an example of what that might look like:

class ReservationSerializer(serializers.ModelSerializer):
    reservation_details = DetailsReservationSerializer(many=True)
    class Meta:
        model = Reservation
        fields = '__all__'

    def create(self, validated_data):
        details_data = validated_data.pop('reservation_details') #grab the data on details
        reservation = Reservation.objects.create(**validated_data) # create the master reservation object
        for reservation_detail in details_data:
            # create a details_reservation referencing the master reservation
            DetailsReservation.objects.create(**reservation_detail, reservation=reservation)
        return reservation

Also one small note, I'd recommend renaming Reservation and Quantity in DetailsReservation to be lowercased as they refer to instances, not classes. My code works once that change is made, however, changing reservation=reservation in the DetailsReservation.objects.create call to Reservation=reservation will make the code work with your code in its current state.

Upvotes: 3

Related Questions