Search code examples
djangodjango-formsforeign-keys

Unable to edit an object which has a foreign key in Django


I want to edit an object that has a foreign key in it. The problem that I am facing is that instead of editing the current object it is creating a new one. I think the issue is caused because of foreign key because in models that do not have foreign keys, I am able to edit their objects without any problem.

models.py

class Room(models.Model):
    class Meta:
      ordering = ['room_number']
    room_number =  models.PositiveSmallIntegerField(
        validators=[MaxValueValidator(1000), MinValueValidator(1)],
        primary_key=True
        )
    ROOM_CATEGORIES = (
        ('Regular', 'Regular'),
        ('Executive', 'Executive'),
        ('Deluxe', 'Deluxe'),
        ('King', 'King'),
        ('Queen', 'Queen'),
    )
    category = models.CharField(max_length=9, choices=ROOM_CATEGORIES)
    ROOM_CAPACITY = (
        (1, '1'),
        (2, '2'),
        (3, '3'),
        (4, '4'),
    )
    capacity = models.PositiveSmallIntegerField(
        choices=ROOM_CAPACITY, default=2
        )
    
    advance = models.PositiveSmallIntegerField()
    room_manager = models.CharField(max_length=30)


class TimeSlot(models.Model):
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    available_from = models.TimeField()
    available_till = models.TimeField()

views.py

def edit_time_slots(request, pk):
    if pk:
        try:
            time_slot_obj = TimeSlot.objects.get(pk=pk)
        except Exception:
            return HttpResponse("Bad request.")
    else:
        return HttpResponse("Bad request.")

    if request.method == 'POST':
        form = AddTimeSlotForm(request.POST, instance=time_slot_obj)
        if form.is_valid():
            try:
                Room.objects.get(room_number=time_slot_obj.room.room_number, room_manager=request.user.username)
            except Exception:
                return HttpResponse("Bad request.")
            time_slot = TimeSlot(room=time_slot_obj.room,
                    available_from=request.POST['available_from'],
                    available_till=request.POST['available_till'])
            time_slot.save()
            # Implemented Post/Redirect/Get.
            return redirect(f'../../view_time_slots/{time_slot_obj.room.room_number}/')

        else:
            context = {
                'form': form,
                'username': request.user.username
                }
            return render(request, 'add_time_slots.html', context)
    context = {
            'form': AddTimeSlotForm(instance=time_slot_obj),
            'username': request.user.username
            }
    return render(request, 'edit_time_slots.html', context)

Link to GitHub repo


Solution

  • You are creating a new TimeSlot instance:

    time_slot = TimeSlot(room=time_slot_obj.room,
                        available_from=request.POST['available_from'],
                        available_till=request.POST['available_till'])
    

    Instead of doing that, modify the existing instance:

    time_slot_obj.available_from = ...
    time_slot_obj.available_till = ...
    time_slot_obj.save()