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

Django预订系统编辑功能报错:__init__()收到意外参数'id'

Django预订系统编辑功能报错解决

核心错误原因

你遇到的TypeError: __init__() got an unexpected keyword argument 'id'是因为混用了类视图和函数视图:

  • URL配置指向了EditBooking类,但Django会将URL中的id参数传递给类的构造函数__init__,而你定义的__init__没有接收该参数。
  • 你在类内部写了函数视图edit_booking,这不符合Django视图规范,类视图需要继承基类并实现特定方法,而非在类中嵌套函数视图。

分步修复方案

1. 修正视图实现

方案A:改用纯函数视图(贴合你原有逻辑)

删除EditBooking类,直接保留并修正edit_booking函数:

from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .models import Booking, UserProfile
from .forms import BookingForm

@login_required
def edit_booking(request, id):
    booking = get_object_or_404(Booking, id=id)
    
    # 权限校验:仅允许用户编辑自己的预订
    if booking.booking_customer.user != request.user:
        messages.error(request, "你无权编辑此预订")
        return redirect('profile')
    
    template_name = 'edit_booking.html'
    if request.method == 'POST':
        form = BookingForm(request.POST, instance=booking)
        if form.is_valid():
            instance = form.save(commit=False)
            # 关联当前登录用户的UserProfile(修正模型字段名错误:原代码用customer_data,模型里是booking_customer)
            instance.booking_customer = UserProfile.objects.get(user=request.user)
            instance.save()
            messages.success(request, '感谢!你的预订已更新!')
            return redirect('profile')  # 保存后跳转回个人页面
        else:
            messages.error(request, '更新失败,请检查表单错误')
    else:
        # 直接用booking实例初始化表单,无需手动编写initial
        form = BookingForm(instance=booking)
    
    return render(request, template_name, {'form': form, 'booking': booking})

方案B:改用类视图(符合Django规范)

如果想用类视图,继承UpdateView而非DetailView,并添加登录校验:

from django.views.generic.edit import UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages
from django.urls import reverse_lazy
from django.shortcuts import redirect
from .models import Booking
from .forms import BookingForm

class EditBooking(LoginRequiredMixin, UpdateView):
    model = Booking
    form_class = BookingForm
    template_name = 'edit_booking.html'
    success_url = reverse_lazy('profile')
    pk_url_kwarg = 'id'  # 指定URL参数名为id,保持和原有URL一致
    
    def get_object(self, queryset=None):
        obj = super().get_object(queryset)
        # 权限校验
        if obj.booking_customer.user != self.request.user:
            messages.error(self.request, "你无权编辑此预订")
            return redirect('profile')
        return obj
    
    def form_valid(self, form):
        messages.success(self.request, '感谢!你的预订已更新!')
        return super().form_valid(form)
    
    def form_invalid(self, form):
        messages.error(self.request, '更新失败,请检查表单错误')
        return super().form_invalid(form)

2. 修正URL配置

  • 如果用函数视图,URL指向函数:
path('edit-booking/<int:id>', views.edit_booking, name='editbooking'),
  • 如果用类视图,需要调用as_view()方法:
path('edit-booking/<int:id>', views.EditBooking.as_view(), name='editbooking'),

3. 修正表单错误

表单里存在两处关键问题,需要调整:

from django import forms
from django.core.exceptions import ValidationError
from django.utils import timezone
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from .models import Booking, TIME_SLOTS, TABLE_SIZE
from django_summernote.widgets import SummernoteWidget

class BookingForm(forms.ModelForm):
    """ 
    Provides necessary fields to the booking form for customers
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Crispy form helpers
        self.helper = FormHelper()
        self.helper.form_method = 'post'        
        self.helper.add_input(Submit('submit', 'Submit', css_class='btn btn-secondary btn-brown mb-4 mx-auto px-5'))        

    # 日期字段优化:移除默认value,让表单自动填充现有预订日期
    booking_date = forms.DateField(
        widget=forms.DateInput(attrs={'class':'form-control', 'type':'date'}), 
        required=True
    )
    booking_time = forms.ChoiceField(choices=TIME_SLOTS, required=True)
    table_size = forms.ChoiceField(choices=TABLE_SIZE, required=True)
    additional_info = forms.CharField(
        max_length=400, 
        widget=SummernoteWidget(), 
        required=False
    )

    class Meta:
        model = Booking
        fields = ['booking_date', 'booking_time', 'table_size', 'additional_info']
        # booked_on是自动生成字段,无需在表单中展示
        readonly_fields = []

    # 日期校验:改用Django表单规范的clean_xxx方法
    def clean_booking_date(self):
        booking_date = self.cleaned_data.get('booking_date')
        if booking_date < timezone.localdate():        
            raise ValidationError("日期不能是过去的时间!")
        return booking_date
  • 移除了Form中重复定义的slug字段(模型已配置AutoSlugField,无需在表单中处理)
  • 将日期校验逻辑改为clean_booking_date方法,符合Django表单验证规范
  • 修正了字段必填性(原代码设为required=False,但预订日期、时间、桌型应为必填项)

4. 模板调整

确保模板中的URL参数与配置一致:

  • profile.html中的编辑按钮:
<a href="{% url 'editbooking' id=booking.id %}" aria-label="edit booking">
    <button type="button" class="btn btn-secondary btn-brown px-5">Edit</button>
</a>
  • edit_booking.html中的表单action:
<form method="POST" action="{% url 'editbooking' id=booking.id %}" class="col-6">                                  
    {% csrf_token %}
    {% crispy form %}
</form>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 04:45:56