I am trying to make a cabbie accept accept a ride but couldn’t.
FOREIGN KEY constraint fail
Ride is available to accept when it is created and is in temporary phase
While accepting the cabbie and his vehicle will be assigned to ride
But Foreign Key constraint fails
Model:
class Ride(models.Model):
STATUS_CHOICES = [
('Temporary', 'Temporary'),
('Passenger Confirmed', 'Passenger Confirmed'),
('Cabbie Confirmed', 'Cabbie Confirmed'),
('Cancelled', 'Cancelled'),
('Completed', 'Completed'),
]
pick_up = models.ForeignKey(Location, on_delete=models.PROTECT, related_name='pick_up')
drop = models.ForeignKey(Location, on_delete=models.PROTECT, related_name='drop')
distance = models.DecimalField(decimal_places=2, max_digits=7)
fare = models.DecimalField(decimal_places=2, max_digits=7)
passenger = models.ForeignKey(User, on_delete=models.PROTECT, related_name='rides')
cabbie = models.ForeignKey(User, on_delete=models.PROTECT, related_name='driven_rides', null=True, blank=True)
vehicle_type = models.ForeignKey(VehicleType, on_delete=models.PROTECT, related_name='rides', null=True, blank=True)
vehicle = models.ForeignKey(Vehicle, on_delete=models.PROTECT, related_name='rides', null=True, blank=True)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='Temporary')
accepted_at = models.DateTimeField(null=True, blank=True)
completed_at = models.DateTimeField(null=True, blank=True)
def calculate_fare(self):
return (self.distance * self.vehicle_type.farekm) + self.vehicle_type.charges
def __str__(self):
return f"Ride from {self.pick_up} to {self.drop} - Status: {self.status}"
View:
def accept_ride(request, ride_id):
# Fetch the ride object or return 404 if not found
ride = get_object_or_404(Ride, id=ride_id)
# Check if the user is a Cabbie
if not request.user.groups.filter(name='Cabbie').exists():
messages.error(request, "You must be a cabbie to accept this ride.")
logger.info(f"User {request.user.username} attempted to accept a ride but is not a cabbie.")
return redirect('CabbieDashboard')
if request.method == 'POST':
try:
# Ensure the ride status is appropriate for acceptance
if ride.status != 'Temporary':
messages.error(request, "This ride cannot be accepted at its current status.")
logger.info(f"Ride {ride.id} cannot be accepted as it is in status {ride.status}.")
return redirect('available_rides')
# Validate if the user has an assigned vehicle
vehicle = getattr(request.user, 'vehicle', None)
if not vehicle:
messages.error(request, "You need an assigned vehicle to accept this ride.")
logger.warning(f"User {request.user.username} attempted to accept a ride without an assigned vehicle.")
return redirect('CabbieDashboard')
# Log the values of foreign keys before assigning
logger.debug(f"Attempting to assign ride with: Cabbie={request.user.id}, "
f"Vehicle={vehicle.id if vehicle else 'None'}, Vehicle Type={ride.vehicle_type.id if ride.vehicle_type else 'None'}, "
f"Pick-up={ride.pick_up.id}, Drop={ride.drop.id}")
# Check if vehicle type matches the ride requirement
if vehicle.type != ride.vehicle_type:
messages.error(request, "Your vehicle does not match the required type for this ride.")
logger.warning(f"User {request.user.username} has vehicle type {vehicle.type} but ride requires {ride.vehicle_type}.")
return redirect('available_rides')
# Assign the current user to the cabbie field and set the correct vehicle
ride.cabbie = request.user
ride.vehicle = vehicle
ride.status = 'Cabbie Confirmed'
ride.accepted_at = timezone.now()
# Validate all fields and log foreign key constraints
ride.full_clean() # Validate the model instance against constraints
ride.save() # Attempt to save the ride
messages.success(request, "Ride accepted successfully.")
logger.info(f"Ride {ride.id} successfully accepted by cabbie {request.user.username}.")
return redirect('ride_detail', ride_id=ride.id)
except Exception as e:
# Log the error with specific foreign key field information
logger.error(f"Error accepting ride {ride_id} by user {request.user.username}: {e}")
messages.error(request, "An error occurred while accepting the ride. Please try again.")
return redirect('available_rides')
# Render the acceptance page with the ride details
return render(request, 'rides/accept_ride.html', {'ride': ride})
I want that Ride object should get updated successfully i.e. Ride is accepted