0

I'm new to Django and am trying to create a small website where I click on a flag and the language changes. I'm using django i18n for that:

urls.py

from django.conf.urls import patterns, include, url
from django.conf.urls.i18n import i18n_patterns

urlpatterns = [url(r'^i18n/', include('django.conf.urls.i18n'))]

urlpatterns += i18n_patterns(
    url(r'^$', views.home, name='home'),
)

The problem is, when I run the following code:

templetatags.py

@register.simple_tag
def test():
    r = requests.post('http://localhost:8000/i18n/setlang/', data = {'lang':'en', 'next' : '/'})
    print r.status_code

home.html

<div id='country_flags'>
    <a hreflang="en" href="{% test %}"><img id='en' src='{% static "mysyte/images/gb.png" %}'></a>
</div>

the result of r.status_code is 403.

What am I doing wrong?

msTOM
  • 11
  • 1
  • Does the view `views.home` require a CSRF token when accepting post data? – John Gordon Sep 23 '16 at 18:55
  • Oh my god, that is my problem, I completely forgot about the CSRF token. Is there a way I can pass the token along with my request? – msTOM Sep 23 '16 at 19:17
  • Why are you doing this? Why would a *template tag* cause a post, and to your own app? – Daniel Roseman Sep 23 '16 at 20:37
  • I think you can include a `csrfmiddlewaretoken` item in your input data dictionary. However you can't give it just any value; it has to be the same value that the CSRF middleware layer is expecting, and I don't know how to get that value easily. – John Gordon Sep 23 '16 at 22:19
  • I'm using a POST because when using the Django translation, according to their documentation, the only way to manually set a language is sending a POST request to the URL i18n/setlang. https://docs.djangoproject.com/en/1.10/topics/i18n/translation/#django.views.i18n.set_language – msTOM Sep 26 '16 at 16:34

1 Answers1

2

Any POST request in django requires you to send the CSRF-Cookie by default. Your options around this:

  • Don't use a POST request. Use GET instead.
  • Send the CSRF-Token with the request. https://docs.djangoproject.com/en/1.9/ref/csrf/
  • use the decorator @csrf_exempt to remove any csrf-protection from a view (in your case the view for http://localhost:8000/i18n/setlang/)
  • don't send a request to your own app. use a link for the user to click on. probably your best option.

Note: if you want to use the decorator w/ a class-based view, decorate the dispatch() function of that view

ht_
  • 346
  • 1
  • 5
  • Thank you for the options, ht_! The only reason I'm using a POST request is because, according to the Django documentation, the view responsible for changing the language of a website (set_language redirect view) only accepts POST requests to the i18n/setlang URL. But I'll try the other options. – msTOM Sep 26 '16 at 16:45