如何在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
相关产品推荐
相关产品推荐

