HenryM
HenryM

Reputation: 5793

How do I pass request to a form in test

I am trying to pass request to a Django form in unittest. This is my test:

def test_AddPairedStudyForm(self):
    self.client.force_login(self.user)
    request = RequestFactory().get(reverse("researcher_ui:console"))
    request.user = self.user

    study_group = 'StudyGroup'
    payload = {
        "study_group": study_group,
        "paired_studies": [self.study.id, self.study1.id],
        'request': request
    }
    form = AddPairedStudyForm(data=payload)
    self.assertTrue(form.is_valid())

This generates a key error in the form: KeyError: 'request'

Within the form itself, this error occurs during the __init__ function

def __init__(self, *args, **kwargs):
    self.request = kwargs.pop("request")
    super(AddPairedStudyForm, self).__init__(*args, **kwargs)

Within the CBV I add the request using the get_form_kwargs function:

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

How can I pass the request to the form in unittest?

Upvotes: 0

Views: 37

Answers (1)

Maxim Danilov
Maxim Danilov

Reputation: 3350

The best way to avoid the problem in general with a form is to remember that the form must be stateless. This is usually not a problem in django, but some fields, such as fields with relationships, retain state. If you add a request to the form directly, as in your example:

class AddPairedStudyForm(forms.Form)

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super().__init__(*args, **kwargs)

this changes the state of the form instance directly. Another suggestion is to add a request to the form initial.

...
form = AddPairedStudyForm(data=payload, initial={'request': request})
...

You can then find the request in initial everywhere in the form.

class AddPairedStudyForm(forms.Form)

    def clean(self, *args, **kwargs):
        data = super().clean(*args, **kwargs)
        ...
        request = self.initial.get('request')
        # validate something accordingly request
        ...
        return data

You can see, you don't need to override __init__ only for remove request from **kwargs.

More about initial here: https://docs.djangoproject.com/en/5.0/ref/forms/api/#initial-form-values

Upvotes: 0

Related Questions