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

Django表单传instance参数初始化报错的解决求助

问题:TypeError: BaseForm.init() got an unexpected keyword argument 'instance'

尝试实现课程更新视图,通过主键将Lesson模型数据预填充到update_requests.html页面,但访问/admin_update/2/时触发上述错误。

错误回溯

Internal Server Error: /admin_update/2/
Traceback (most recent call last):
  File "/Users/jaeholee/SEG-Small-Group-Project/hyena/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/Users/jaeholee/SEG-Small-Group-Project/hyena/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/jaeholee/SEG-Small-Group-Project/hyena/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/jaeholee/SEG-Small-Group-Project/hyena/lessons/views.py", line 60, in AdminUpdateRequests
    form = AdminLessonForm(instance=lesson)
TypeError: BaseForm.__init__() got an unexpected keyword argument 'instance'

核心问题原因

AdminLessonForm继承自forms.Form(普通表单类),该类不支持instance参数——只有forms.ModelForm(模型表单类)才支持通过instance绑定模型实例,实现预填充和更新操作。

相关代码片段

urls.py

path('admin_update/<str:pk>/', views.AdminUpdateRequests, name='admin_update'),

views.py

def AdminUpdateRequests(request, lesson_id):
    lesson = Lesson.objects.get(pk=lesson_id)
    form = AdminLessonForm(request.POST or None, instance=lesson)
    context = {
        'lesson':lesson, 'form':form
    }
    return render(request, 'admin/update_requests.html',context)

forms.py

class AdminLessonForm(forms.Form):
    """Form enabling admin users to create new lessons."""
    subject_choices  = [(i, i) for i in Lesson.subjects()]
    duration_choices = [(i, i) for i in Lesson.durations()]
    interval_choices = [(i, i) for i in Lesson.intervals()]
    lesson_request = forms.ModelChoiceField(label="Lesson Request",queryset=Lesson.objects.filter(is_request=True), widget=forms.Select(attrs={"class":"form-control"}))
    lesson_name    = forms.ChoiceField(label="Lesson name", choices=subject_choices, widget=forms.Select(attrs={"class":"form-control"}))
    teacher        = forms.ModelChoiceField(label="Teacher",queryset=Teacher.teacher.all(), widget=forms.Select(attrs={"class":"form-control"}))
    start_time     = forms.DateTimeField(label="Start time [Day/Month/Year Hour:Minute]",input_formats=['%d/%m/%Y %H:%M'],
                                        widget=forms.DateTimeInput(format='%d/%m/%Y %H:%M',attrs={'class':'form-control'}))
    interval       = forms.ChoiceField(label="Interval [Days]", choices=interval_choices, widget=forms.Select(attrs={"class":"form-control"}))
    duration       = forms.ChoiceField(label="Duration [Minutes]", choices=duration_choices, widget=forms.Select(attrs={"class":"form-control"}))
    number         = forms.IntegerField(label="Number of Lessons", widget=forms.NumberInput(attrs={"class":"form-control"}))

    def save(self):
        """Create a new lesson."""
        request = self.cleaned_data.get('lesson_request')
        lesson = Lesson.objects.create(
            lesson_name = self.cleaned_data.get('lesson_name'),
            student     = request.student,
            teacher     = self.cleaned_data.get('teacher'),
            start_time  = self.cleaned_data.get('start_time'),
            interval    = int(self.cleaned_data.get('interval')),
            duration    = int(self.cleaned_data.get('duration')),
            number      = self.cleaned_data.get('number'),
            is_request  = False,
        )
        lesson.price = self.calculate_price(lesson.duration, lesson.number)
        request.delete()
        return lesson

解决方案

1. 修改表单类为ModelForm

将AdminLessonForm改为继承forms.ModelForm,并通过Meta类关联Lesson模型,同时保留原有字段的验证和样式:

class AdminLessonForm(forms.ModelForm):
    """Form enabling admin users to update existing lessons."""
    subject_choices  = [(i, i) for i in Lesson.subjects()]
    duration_choices = [(i, i) for i in Lesson.durations()]
    interval_choices = [(i, i) for i in Lesson.intervals()]

    # 重写字段以保留原有选择项和样式
    lesson_name = forms.ChoiceField(label="Lesson name", choices=subject_choices, widget=forms.Select(attrs={"class":"form-control"}))
    interval = forms.ChoiceField(label="Interval [Days]", choices=interval_choices, widget=forms.Select(attrs={"class":"form-control"}))
    duration = forms.ChoiceField(label="Duration [Minutes]", choices=duration_choices, widget=forms.Select(attrs={"class":"form-control"}))
    teacher = forms.ModelChoiceField(label="Teacher", queryset=Teacher.teacher.all(), widget=forms.Select(attrs={"class":"form-control"}))
    start_time = forms.DateTimeField(label="Start time [Day/Month/Year Hour:Minute]", input_formats=['%d/%m/%Y %H:%M'],
                                    widget=forms.DateTimeInput(format='%d/%m/%Y %H:%M', attrs={'class':'form-control'}))

    class Meta:
        model = Lesson
        fields = ['lesson_name', 'teacher', 'start_time', 'interval', 'duration', 'number', 'is_request']  # 选择需要更新的字段

    def save(self, commit=True):
        # 重写save方法,保留价格计算逻辑
        lesson = super().save(commit=False)
        lesson.price = self.calculate_price(lesson.duration, lesson.number)
        lesson.updated_at = timezone.now()  # 更新修改时间
        if commit:
            lesson.save()
        return lesson

    def calculate_price(self, duration, number):
        # 保留原有的价格计算逻辑
        # 补充你原有的calculate_price实现
        pass

2. 修正视图函数逻辑

更新AdminUpdateRequests,处理表单提交后的更新操作,并修正URL参数类型(主键为整数,用int而非str):

先修改urls.py

path('admin_update/<int:pk>/', views.AdminUpdateRequests, name='admin_update'),

再修改views.py

def AdminUpdateRequests(request, pk):
    lesson = Lesson.objects.get(pk=pk)
    if request.method == 'POST':
        form = AdminLessonForm(request.POST, instance=lesson)
        if form.is_valid():
            form.save()
            return redirect('admin_manage_requests')  # 跳转到课程管理页面
    else:
        form = AdminLessonForm(instance=lesson)
    context = {'lesson': lesson, 'form': form}
    return render(request, 'admin/update_requests.html', context)

3. 移除不必要的字段

原表单中的lesson_request字段是用于创建新课时关联请求的,更新课时时不需要该字段,因此在ModelForm中删除该字段。

验证修改

启动Django服务,重新访问/admin_update/2/,此时表单会自动预填充对应Lesson实例的数据,提交表单后即可完成更新操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 14:25:20