How to pass self.request data in django form?

37 views Asked by At

I want to pass self.request data in the form class. I can access it in View, but unable to access it in form class.

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

My Form class:

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)
        
        # This I need to be done
        # 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
        

I want to set subject_name choices according to the request values passed. For class 1, I want different subject choices., and for class 2, different subject choices etc. So getting request data is important.

Is there any way to set the initial choice in direct View like I did for class_name? Or any suggestions on how to do it in form?

1

There are 1 answers

0
willeM_ Van Onsem On BEST ANSWER

Pass the request through the form_kwargs:

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

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

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

and then we handle this in the form:

class AttendanceForm(forms.ModelForm):
    # …

    def __init__(self, *args, request, **kwargs):
        self.request = request
        super().__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

Note: Since PEP-3135 [pep], you don't need to call super(…) with parameters if the first parameter is the class in which you define the method, and the second is the first parameter (usually self) of the function.