You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django含外键对象无法编辑:修改时新建对象问题

编辑含外键的TimeSlot对象时新建而非更新的问题解决

编辑包含外键的TimeSlot对象时,执行修改操作并未更新原有对象,而是新建了一个新对象。无外键的模型对象可正常编辑,推测问题与外键有关。

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)

问题原因与修复

问题和外键无关,核心错误是在POST处理逻辑中手动新建了TimeSlot实例,没有对获取到的原有time_slot_obj进行更新。

代码中已经正确初始化了带instance=time_slot_obj的表单,直接调用form.save()就能完成原有对象的更新,无需重新构造TimeSlot对象。

修改后的POST处理代码如下:

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.")
        # 直接保存表单,自动更新原有实例
        form.save()
        return redirect(f'../../view_time_slots/{time_slot_obj.room.room_number}/')

另外,避免直接从request.POST取值,表单已完成数据验证和清洗,使用form.save()是更安全、符合Django开发规范的做法。

内容的提问来源于stack exchange,提问作者Anshul Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:06:01