Reputation: 335
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
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
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