Can't Get CSRF Token to Appear on a Django Template/View - django

I'm trying to use a Django ListView sub-class to generate a page with a form on it. It's an old school manual HTML form, not a Django-generated one (though I do also have a Django-generated form elsewhere on the same page). Since Django bakes CSRF authentication in, I need to include the CSRF token in that form in order to make it work.
However, I'm not having much luck, even after looking at several related Stack Overflow posts (and fixing things accordingly).
Basically I've got a get method on a ListView subclass, and I've used the method decorator to decorate it with the CSRF decorator:
class FooView(ListView):
#method_decorator(ensure_csrf_cookie)
def get(self, request):
# code for otherwise working view
In my template I have:
<form>
{% csrf_token %}
However, when I view the source of the page after it's been rendered, I just see:
<form>
(no CSRF token).
I'm not explicitly adding the CSRF token to the context because I'm using ListView, and as per https://docs.djangoproject.com/en/1.6/ref/contrib/csrf:
If you are using generic views or contrib apps, you are covered already
I'm sure I'm just missing something basic, but any help explaining what that might be would be greatly appreciated.

You need import this:
from django.template import RequestContext
and then use it like so:
def example():
# Some code
return render_to_response('my_example.html', {
'Example_var':my_var
}, context_instance=RequestContext(request))
This will force a {% csrf_token %} to appear.

Related

Restricting Access to Django's success_url()

New Django user here.
I am trying to restrict access to Django's success_url() upon GET requests. I realize I am not the first to ask this question, however, I am specifically trying to achieve this in conjunction with Django's generic class-based views. Generic views seem cleaner, faster, and more idiomatic. I want to use them as much as possible unless they are absolutely unfit for the job.
Basically, I am creating a simple contact form for non-users who only want to send me a message without creating an account. I've created a contact app to handle these types of contacts. I've created a ModelForm, which I am rendering with a contact.html with Django's FormView. After a person submits the form, they will receive a cool looking thank you message, rendered with a thanks.html, which has its own url.
But I only want them to see the thank you message if they POST the contact form. Currently, you can go on my site and type '/contact/thanks/', and my thanks.html will be rendered whether you've submitted a form or not. Django's success_url apparently defaults to a GET request.
Here's my view:
class MyContact(FormView):
template_name = 'contact.html'
form_class = ContactForm
success_url = 'thanks'
Here's my form:
ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = ['email_address', 'message_body']
Here's the html form in contact.html:
<form action="" method="POST">{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="send btn btn-secondary">Send Message</button>
</form>
My first thought was to decorate my contact app url with a require_POST() decorator like this:
urlpatterns = [
url(r'^thanks/$', require_POST(views.ThanksPageView.as_view()), name='thanks'),
]
This doesn't work because Django's success_url() defaults to a GET request.
What is the most idiomatic way to approach this? Since Django is a 'batteries included' framework, I do not want to use 'duck-tape', meaning I do not want implement any ad-hoc logic in my views or urls.
Sorry if I've missed anything in the docs or questions archive.
Since you're asking for a idiomatic approach, I would consider the messages framework and specifically the SuccessMessageMixin. This would allow you to add a success message to e.g. the contact form itself and the url-pattern for the /thanks/ page would not be necessary.

Forms with and without csrf tokens on single page

I have a login form on every page that's a popup, and it requires the csrf token.
I also have some form views that have a form that doesn't require the csrf token.
What I've found is that even if I have the {% csrf_token %} on the login form, if the view isn't wrapped with csrf_protect() it doesn't generate the token, so when the login form is submitted, it gets a csrf missing error. OTOH, if I do wrap it, then the other form on the page that doesn't need it complains about it missing though the login form works. One form submits to the current page form view, while the form submits to a separate form view.
Is it possible to get the csrf_token to generate even without the csrf_protect being used?
I saw the csrf_exempt function but it doesn't help when wrapping the view either. Is it possible to render two view functions or wrap it within the template? I'm just using a {% include login.html %}
Thanks

Mako csrf_token like in Django templates

I my recent Django-project I use mako templates.
About Cross Site Request Forgery CSRF.
In django templates there is the tag {% csrf_token %} to protect from hackers.
What about mako templates? Is there any analog of csrf_token or there is another protection mechanism???
Thanks!
I ran into the same problem just today (that's why I ended up here). I found a solution, at least, for what I wanted to do, which is pass some POST data to another view through an HTML form. Here it is:
From your first view, get a CSRF Token and add it to your (Mako) context:
from djangomako.shortcuts import render_to_response as render
from django.core.context_processors import csrf
def first_view(request):
"""This view generates a form whose action is 'second_view'."""
context = { "csrftoken": csrf(request)["csrf_token"] }
return render("path/to/yourtemplate.html", context)
yourtemplate.html's form must have a field named “csrfmiddlewaretoken” whose value is the CSRF Token, which we placed in the context as “csrftoken”. As in:
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrftoken }" />
Source: Cross Site Request Forgery protection (Django 1.5 Docs)
There's some sample code at Django Snippets that looks to do this, although judging by the comments, you may need to fiddle a bit. If you have trouble, you basically want to make sure that you're duplicating the Django stock CSRF tag (click the link, start on line 87).

Django: How to include modelform?

{% include 'django.contrib.auth.views.login' %}
I don't want to write everything by hand.. I hate this really, django full of automatic stuff.
Goal is to include registration/login.html into base.html, so that I could have this form in every page
If I include only template itself (registration/login.html), problem appears that "form.login", I mean "form" var is not defined because this one comes from VIEW which called when you going to login url. So how can I call that view MANUALLY with include or at least to grab django.contrib.auth.views.login variables by my self in my own view and pass then to base.html?
P.s. It's not just about login form, I think there will be more situations like this
I have found better solution in #django irc.
They called inclusion tags
I'll give you my code, because I got lot's of problem learning new stuff in django =)
file: templatetags/form_login.py
from django import template
register = template.Library()
from django.contrib.auth.forms import AuthenticationForm
#register.inclusion_tag('registration/login.html')
def form_login():
return { 'form': AuthenticationForm() }
Now you can have your form anywhere, this will prerender template and THAT'S IT! no stupid context processors which requires to modify whole project settings.py, which is really sux if you writing stand alone little application..
If you need login-form on every page
Create a context processor:
def login_form_processor(request):
return {
'login_form': LoginForm(request.POST or None)
}
Add it to settings.CONTEXT_PROCESSORS.
Include the template for login form:
{% with login_form as form %}
{% include "registration/login.html" %}
{% endwith %}
You can also make you form lazy-loading, so form will not be created until it is used for the first time.
from django.utils improt functional
def login_form_processor(request):
create_login_form = lambda: LoginForm(request.POST or None)
return {
'login_form': functional.lazy(create_login_form, LoginForm)
}
But I guess you won't want the lazy-loading feature, because login-form is cheap to initialize.
Reusing views
Concerning the "grabbing variables" part from your question: you cannot grab variable from view. Django view is method which returns response object. You can not get variables from response. However some of views accept extra_context and other attributes. Those attributes allow you to configure those views in urls, or to wrap them with your own view, for example:
def my_login_view(request):
some_extra_data = get_some_data()
extra_context = {
'some_extra_var': some_extra_data
}
return login_view(request, extra_context=extra_context, template="my_template.html")
This is not exactly grabbing the variables from views, more like augmentation of existing views.
If you expect to have more situations like this, do less data-porcessing in views. Call some methods which checks for permissions. Collect some data from context-processors. Return rendered response. Now you can reuse the data in other views.
You can specify the action on the form html to point to the URL that accesses the corresponding view.
If you want a form, say called as login_form always populated in all templates, then put it in the context_processors.
Browsing the code for django.contrib.auth.views, you will see that the variables form, site and *site_name* are passed to the template.
Either you (1) provide your custom registration form or (2) you can just import django.contrib.auth.forms.AuthenticationForm in your view if you want to use it.

Beginner authentication question

I have a page, index.html, that contains both a login and registration form. I have a couple of questions about getting this to work properly
My URLConfig looks like this:
urlpatterns = patterns('djangoproject1.authentication.views',
(r'^$',direct_to_template,{'template':'authentication/index.html'}),
(r'^register/$','register'),
)
1) Using the Django book is a guide, my form looks like this:
<h1>Register</h1>
<form action="/register/" method="post">
{{ form.as_p }}
<input type="submit" value="Register">
</form>
Of course, since the file is index.html, the form doesn't appear when I just go to the page. Do I need a "view" to handle visiting index.html rather than a direct_to_template?
2) My Register code looks like this:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
return HttpResponseRedirect("/register/success/")
else:
form = UserCreationForm()
return render_to_response("authentication/index.html", {'form': form})
This is the django authentication built-in stuff. Do people actually use it? It seems limited. I know I can add more fields to the Django User by using a user profile or something, but what about the UserCreationForm? Should I roll my own form? Should it inherit from UserCreationForm somehow?
direct_to_template by itself can neither produce nor handle forms -- it simply renders a request directly to a template, as its name describes.
You might look into django-registration for registration.
If you're putting two forms on the same page, you'll need a custom view that is capable of rendering and handling both forms, though multi-form pages are notoriously tricky to work with properly. If you have separate forms (and submit buttons), you can add a unique name to each submit input and determine which form (class) to validate and handle based on if name in request.POST.
edit:
After looking more closely at your code, I see that your registration form redirects to a different view; that simplifies things, but you'll still need a custom view for your home page that passes both login and registration forms to the template for rendering.
Alternatively, if you're simply redirecting to pages that handle each form, you can add those forms using direct_to_template's extra_context parameter directly in your urls.py:
from wherever import LoginForm, RegistrationForm
urlpatterns = patterns('djangoproject1.authentication.views',
(r'^$',
direct_to_template,
{
'template': 'authentication/index.html',
'extra_context': {
'reg_form': RegistrationForm(),
'login_form': LoginForm()
}
}
),
(r'^register/$', 'register'),
)
This approach isn't the cleanest, but it's an option if you really wanted to use generic views.
It sounds like you'll probably want to use a different generic view instead of direct_to_tepmlate. Take a look at the create object generic view. I usually just create a view, typically I end up needing to do more than what a generic view will allow me to do easily.