Aiden Campbell
Aiden Campbell

Reputation: 335

How can I update a field on a foreign key when creating a new object?

Im quite new to Django and im having a problem with a model.

class RestaurantAvailability(models.Model):
    """RestaurantAvailability Model"""
    DayTime = models.DateTimeField()
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
    availability = models.IntegerField(null=True)

    def __str__(self):
        """What to show when we output an object as a string."""
        restaurant = self.restaurant.name
        time = self.DayTime
        return restaurant + " " + str(time)


class Reservation(models.Model):
    """Reservation Model"""
    name=models.CharField(max_length=100)
    email=models.CharField(max_length=100)
    note=models.CharField(max_length=100)
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
    restaurantAvailability = models.ForeignKey(RestaurantAvailability, on_delete=models.CASCADE)

    def __str__(self):
        """What to show when we output an object as a string."""
        person = self.name
        place = self.restaurant.name
        time = self.restaurantAvailability.DayTime
        return person + "  " + place + " " + str(time)

    def save(self, *args, **kwargs):
        """decrement resturant avalability by 1 on create"""
        if not self.pk:
            print('|||||||||||||||||||||||||||||||||||||||||')
            print(self.restaurantAvailability.availability)
            print('|||||||||||||||||||||||||||||||||||||||||')
            self.restaurantAvailability.availability -= 1 #  decrement resturant avalability by 1 on create
            print(self.restaurantAvailability.availability)
        super(Reservation, self).save(*args, **kwargs)

When I create a new Reservation I want to decrement Resturant availability by 1. The save method is running because im successfully creating a new reservation, and I even print out the correct availability after decrement. But when I go to the admin panel to see RestaurantAvailability's I don't see any change in the availability. Its as if the availability is not being saved.

My question is how can I update a field on a foreign key when creating a new object?

Upvotes: 0

Views: 99

Answers (2)

Dalvtor
Dalvtor

Reputation: 3286

You need to save the availability after changing it. Notice the self.restaurantAvailability.save() line. You can also do an update statement instead of calling .save() or move that logic to a signal.

def save(self, *args, **kwargs):
        """decrement resturant avalability by 1 on create"""
        if not self.pk:
            print('|||||||||||||||||||||||||||||||||||||||||')
            print(self.restaurantAvailability.availability)
            print('|||||||||||||||||||||||||||||||||||||||||')
            self.restaurantAvailability.availability -= 1 #  decrement resturant avalability by 1 on create
            self.restaurantAvailability.save()
            print(self.restaurantAvailability.availability)

Extra: Might be worth looking into making the transaction atomic so you don't have problems with concurrent requests.

from django.db import models, transaction


@transaction.atomic
def save(self, *args, **kwargs):
    ...

Upvotes: 1

schillingt
schillingt

Reputation: 13731

You should handle this with a post_save signal handler.

from django.db.models.signals import post_save
from django.dispatch import receiver


@receiver(post_save, sender=Reservation, dispatch_uid="update_availability")
def update_stock(sender, instance, **kwargs):
    RestaurantAvailability.objects.filter(pk=instance.restaurantAvailability_id).update(availability=F('availability') - 1)

You still need to be worried about concurrent requests generating more reservations than can be handled though.

Upvotes: 1

Related Questions