Django formset unit test Django formset unit test django django

Django formset unit test


In particular, I've found that the ManagmentForm validator is looking for the following items to be POSTed:

form_data = {            'form-TOTAL_FORMS': 1,             'form-INITIAL_FORMS': 0 }


Every Django formset comes with a management form that needs to be included in the post. The official docs explain it pretty well. To use it within your unit test, you either need to write it out yourself. (The link I provided shows an example), or call formset.management_form which outputs the data.


It is in fact easy to reproduce whatever is in the formset by inspecting the context of the response.

Consider the code below (with self.client being a regular test client):

url = "some_url"response = self.client.get(url)self.assertEqual(response.status_code, 200)# data will receive all the forms field names# key will be the field name (as "formx-fieldname"), value will be the string representation.data = {}# global information, some additional fields may go theredata['csrf_token'] = response.context['csrf_token']# management form information, needed because of the formsetmanagement_form = response.context['form'].management_formfor i in 'TOTAL_FORMS', 'INITIAL_FORMS', 'MIN_NUM_FORMS', 'MAX_NUM_FORMS':    data['%s-%s' % (management_form.prefix, i)] = management_form[i].value()for i in range(response.context['form'].total_form_count()):    # get form index 'i'    current_form = response.context['form'].forms[i]    # retrieve all the fields    for field_name in current_form.fields:        value = current_form[field_name].value()        data['%s-%s' % (current_form.prefix, field_name)] = value if value is not None else ''# flush out to stdoutprint '#' * 30for i in sorted(data.keys()):    print i, '\t:', data[i]# post the request without any changeresponse = self.client.post(url, data)

Important note

If you modify data prior to calling the self.client.post, you are likely mutating the DB. As a consequence, subsequent call to self.client.get might not yield to the same data, in particular for the management form and the order of the forms in the formset (because they can be ordered differently, depending on the underlying queryset). This means that

  • if you modify data[form-3-somefield] and call self.client.get, this same field might appear in say data[form-8-somefield],
  • if you modify data prior to a self.client.post, you cannot call self.client.post again with the same data: you have to call a self.client.get and reconstruct data again.