How to add CSRF to context when using test client???

3,126 views
Skip to first unread message

Matteius

unread,
Jun 10, 2011, 12:48:28 AM6/10/11
to Django users
Greetings,

I am writing unit tests for my application, and I want to leave CSRF
checks enabled in testing. This means on my POST I am getting 403
because I have not figured out how to add csrf to my context when
using the test client. Please advise on how to most easily do this:

# Issue a POST request.
response = self.client.post('/student/open_enrollments/',
{'course': 3})
# Check that the response is 200 OK.
self.assertEqual(response.status_code, 200)
# Verify template is the expected one.
self.assertTemplateUsed(response, 'student_portal/
open_enrollments.html')
# Check that the rendered context contains now 0 Courses.
self.assertEqual(len(response.context['courses']), 0)

Artemenko Alexander

unread,
Jun 10, 2011, 2:46:43 AM6/10/11
to Django users
Hi Matt,

Use:

from django.test import Client
csrf_client = Client(enforce_csrf_checks=True)

https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#testing

10.06.2011, 08:48, "Matteius" <matt...@gmail.com>:


> Greetings,
>
> I am writing unit tests for my application, and I want to leave CSRF

> checks enabled in testing. О©╫This means on my POST I am getting 403


> because I have not figured out how to add csrf to my context when

> using the test client. О©╫Please advise on how to most easily do this:
>
> О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫# Issue a POST request.
> О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫response = self.client.post('/student/open_enrollments/',
> {'course': 3})
> О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫# Check that the response is 200 OK.
> О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫self.assertEqual(response.status_code, 200)
> О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫# Verify template is the expected one.
> О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫self.assertTemplateUsed(response, 'student_portal/
> open_enrollments.html')
> О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫# Check that the rendered context contains now 0 Courses.
> О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫self.assertEqual(len(response.context['courses']), 0)
>
> --
> You received this message because you are subscribed to the Google Groups "Django users" group.
> To post to this group, send email to django...@googlegroups.com.
> To unsubscribe from this group, send email to django-users...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Matteius

unread,
Jun 10, 2011, 1:02:26 PM6/10/11
to Django users
Yes I Have this in the setUp function which causes my POST request to
get a 403 forbidden because I don't actually include the CSRF field in
the context as the middleware does on a deployed version of the site.
I need a function to call or something to get the CSRF context value,
or a function that I can pass a context which will add it in the
CSRF. Otherwise there is not much of a point to enable CSRF with the
test client because you'll get 403 errors.

-Matt

On Jun 10, 1:46 am, Artemenko Alexander <sa...@svetlyak.ru> wrote:
> Hi Matt,
>
> Use:
>
> from django.test import Client
> csrf_client = Client(enforce_csrf_checks=True)
>
> https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#testing
>
> 10.06.2011, 08:48, "Matteius" <matte...@gmail.com>:
>
>
>
> > Greetings,
>
> > I am writing unit tests for my application, and I want to leave CSRF
> > checks enabled in testing. This means on my POST I am getting 403
> > because I have not figured out how to add csrf to my context when
> > using the test client. Please advise on how to most easily do this:
>
> > # Issue a POST request.
> > response = self.client.post('/student/open_enrollments/',
> > {'course': 3})
> > # Check that the response is 200 OK.
> > self.assertEqual(response.status_code, 200)
> > # Verify template is the expected one.
> > self.assertTemplateUsed(response, 'student_portal/
> > open_enrollments.html')
> > # Check that the rendered context contains now 0 Courses.

andres ledesma

unread,
Jun 27, 2011, 6:27:43 PM6/27/11
to Django users
Hi Matteius, I stumbled across the same problem.
I wanted to carry out a test case using CSRF, and I failed.
I managed to add the csrf_token to my post request, but
apparently this is not enough. Here I will show you the code,
perhaps you will have better luck then...

c = Client(enforce_csrf_checks=True)
response = c.get('/auction/add/') # get a fresh form
print(response.content) # just to have a look
csrf_token = response.context['csrf_token'] # get the token
print('the token is: %s' % csrf_token) # show me the token

# now, we add the token value to the key csrfmiddlewaretoken
# as this is where django CSRF will check it

post_data = {
'csrfmiddlewaretoken': csrf_token,
'item': 'test item',
'price': '154.78',
'end_date': '2011-08-05 19:30:00',
}
# now we can send the post
response = c.post('/auction/add/', post_data)
# now we test the assert
self.assertEqual(response.status_code, 200)

As I said, this still does not work, I get a 403: which refers
to an invalid CSRF token key. If you managed to overcome this
problem, please let us know. So far, I decided
not to use c = Client(enforce_csrf_checks=True) but this is not
a nice solution, is it?
Best!
-Andres

Craig Blaszczyk

unread,
Jul 7, 2011, 7:02:50 AM7/7/11
to django...@googlegroups.com
csrf_token is a proxy object not a string.

Try doing:
csrf_token = '%s' % response.context['csrf_token']

Matteius

unread,
Aug 24, 2011, 11:54:38 PM8/24/11
to Django users
Thanks for both suggestions, I recently tried this approach and
reached success when I ran my tests. So I think this is the correct
approach and I'll include this CSRF style testing with my test suite
now.

-Matteius

Pratik Mandrekar

unread,
Oct 12, 2013, 10:12:05 AM10/12/13
to django...@googlegroups.com
I'm getting a 401 (Which is technically an Authorization error) after doing this.

c = Client(enforce_csrf_checks=True)

response = c.get(a_url_that_requires_login)

csrfmiddlewaretoken =  '%s' %response.context['csrf_token']

response = c.post(url, data=json.dumps(body), content_type='application/json', X_CSRFToken = csrfmiddlewaretoken)


I also tried with/without updating the session with the token

c.session.update({'csrftoken': csrfmiddlewaretoken})


Any idea why there might be an authorization error?

My permissions are loaded fine from the fixtures.

Thanks,

Pratik
Reply all
Reply to author
Forward
0 new messages