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

如何在Django表单中传递self.request数据?

问题:在Django表单类中获取request数据并动态设置字段选项

我希望在表单类中传递self.request数据,目前可在View中访问它,但无法在表单类中访问。

我的视图代码:

class AttendanceCreateView(LoginRequiredMixin, CreateView):
    model = Attendance
    template_name = 'attendance/attendances_new.html'
    form_class = AttendanceForm

    def get_initial(self):
        initial = super().get_initial()
        initial['class_name'] = self.request.GET.get('class', '')
        return initial

我的表单类代码:

class AttendanceForm(forms.ModelForm):
    class_name = forms.ChoiceField(choices=CLASS_NAMES, disabled=True)
    teacher = forms.ModelMultipleChoiceField(
        queryset=Teacher.objects.all().order_by('id'))
    subject_name = forms.ChoiceField(choices=[])
    total_students = forms.IntegerField(initial=0)
    unique_code = forms.IntegerField(initial=0)

    class Meta:
        model = Attendance
        fields = ['class_name', 'teacher', 'subject_name',
                  'total_students', 'unique_code']

    def __init__(self, *args, **kwargs):
        super(AttendanceForm, self).__init__(*args, **kwargs)
        
        # 我需要实现的逻辑
        # if self.request.GET.get('class', '') = 'class1':
        #    self.fields['subject_name'].choices = MY_CHOICES_1 
        # elif self.request.GET.get('class', '') = 'class2':
        #    self.fields['subject_name'].choices = MY_CHOICES_2

我希望根据传入的request值设置subject_name的选项,如class1对应MY_CHOICES_1,class2对应MY_CHOICES_2,获取request数据十分关键。请问能否像设置class_name那样直接在View中设置初始选项?或有什么在表单中实现的建议?


解决方案

方案一:在View中直接设置字段选项

如果逻辑简单、无需在表单中复用,可以直接在View的get_form方法中修改表单字段的选项:

class AttendanceCreateView(LoginRequiredMixin, CreateView):
    model = Attendance
    template_name = 'attendance/attendances_new.html'
    form_class = AttendanceForm

    def get_initial(self):
        initial = super().get_initial()
        initial['class_name'] = self.request.GET.get('class', '')
        return initial
    
    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        # 获取request中的class参数
        class_param = self.request.GET.get('class', '')
        # 根据参数设置subject_name的选项
        if class_param == 'class1':
            form.fields['subject_name'].choices = MY_CHOICES_1
        elif class_param == 'class2':
            form.fields['subject_name'].choices = MY_CHOICES_2
        return form

方案二:将request传递给表单类处理

如果需要在表单中复用该逻辑,或者逻辑较为复杂,可以通过get_form_kwargs方法将request传入表单:

第一步:修改View类

class AttendanceCreateView(LoginRequiredMixin, CreateView):
    model = Attendance
    template_name = 'attendance/attendances_new.html'
    form_class = AttendanceForm

    def get_initial(self):
        initial = super().get_initial()
        initial['class_name'] = self.request.GET.get('class', '')
        return initial
    
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        # 将request添加到表单的参数中
        kwargs['request'] = self.request
        return kwargs

第二步:修改表单类

class AttendanceForm(forms.ModelForm):
    class_name = forms.ChoiceField(choices=CLASS_NAMES, disabled=True)
    teacher = forms.ModelMultipleChoiceField(
        queryset=Teacher.objects.all().order_by('id'))
    subject_name = forms.ChoiceField(choices=[])
    total_students = forms.IntegerField(initial=0)
    unique_code = forms.IntegerField(initial=0)

    class Meta:
        model = Attendance
        fields = ['class_name', 'teacher', 'subject_name',
                  'total_students', 'unique_code']

    def __init__(self, *args, **kwargs):
        # 从kwargs中取出request,需在调用super()之前弹出,避免父类构造器报错
        self.request = kwargs.pop('request', None)
        super(AttendanceForm, self).__init__(*args, **kwargs)
        
        if self.request:
            class_param = self.request.GET.get('class', '')
            if class_param == 'class1':
                self.fields['subject_name'].choices = MY_CHOICES_1 
            elif class_param == 'class2':
                self.fields['subject_name'].choices = MY_CHOICES_2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:10:28