1

I try to create some Integration tests to test a view in my django project. In my view I create a ModelForm with a prefix

customer_form = CustomerForm(request.POST or None, prefix="customer", instance=customer)

I am trying the following code on my Integration test using django client.

response = self.client.get(reverse("customer_edit", kwargs={"customer_id":customer_id})
customer_form = response.context["customer_form"]
data = customer_form.data
prefix = cutomer_form.prefix

self.client.post(reverse("customer-edit", kwargs={"customer_id":customer_id}, data,  follow=True)

But in my view when I am checking if customer_form is valid i get that it isn't. customer_form.errors has all required fields, although data dictionary contains the values. Does django do something different when prefix is set up on a modelform?

Apostolos
  • 7,763
  • 17
  • 80
  • 150
  • 2
    But that code isn't posting any data. – Daniel Roseman Sep 14 '15 at 20:40
  • edited it...I send data correctly on my real test – Apostolos Sep 14 '15 at 20:43
  • Well it still doesn't seem to make much sense. What is `response.data` and why do you think it has the fields suitable for posting back? – Daniel Roseman Sep 14 '15 at 20:53
  • Sorry man, edited once more....Hope it makes sence more now... – Apostolos Sep 14 '15 at 20:55
  • Still not, I'm afraid. `customer_form.data` will always be an empty dict, because the form is not bound as this a GET request. – Daniel Roseman Sep 14 '15 at 21:21
  • the form gets the customer with instance=customer. So it is bound i think, and data is a non empty dictionary.Also request.POST querydict shows that values are passed with the request – Apostolos Sep 14 '15 at 21:56
  • The form is definitely unbound. The instance is used for the initial values of the form, it does not set the form data. To convince yourself, try printing `customer_form.is_bound` and `customer_form.data` in your test to see what you get. – Alasdair Sep 14 '15 at 22:21
  • you are right about the bound and data. Changing customer_form.data to customer_form.initial gave me the dictionary with the values. Post still says that the fields are required. – Apostolos Sep 14 '15 at 22:31
  • Right, but you have a prefix, which was the whole point of your question. See my answer. – Daniel Roseman Sep 15 '15 at 06:19

2 Answers2

2

You can take the values from the initial dict and add a prefix manually:

data = {"{}-{}".format(prefix, k): v for k, v in customer_form.initial.items()}
Raydel Miranda
  • 13,825
  • 3
  • 38
  • 60
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • This is one of those things that should be transparent to the end user, it is not obvious that if you have a prefixed form, you have to alter the data in order to test it. – Raydel Miranda Apr 13 '19 at 16:14
0

I found the solution for this problem here on this old discontinued post: https://code.djangoproject.com/ticket/13763. I don't know if this is the most elegant way around it, but it was the easiest way for me. Basically you have to put the prefix right before the field name. So the test structure may become something like:

data = {'YOURprefix-fieldName':'anything'}

response = self.client.post(reverse('url_name', kwargs{'foo','bar'}), data)

That way, your views.py is_valid() check bellow will return true (if the data put into the form is valid of course):

form = MyForm(request.POST, prefix=YOURprefix)
if form.is_valid():
...
José N.
  • 11
  • 1