3

views.py:

def index(request):
    return render_to_response('index.html', {})

def photos(request, artist):
    if not artist:
        return render_to_response('photos.html', {'error' : 'no artist supplied'})
    photos = get_photos_for_artist(artist)
    if not photos:
        logging.error('Issue while getting photos for artist')
        return render_to_response('photos.html', {'error': 'no matching artist found'})
    return render_to_response('photos.html', {'photos': photos})  

Index.html:

<html>
    <head>
        <title>find artist photos </title>
    </head>
    <body>
        {% block error %} {% endblock %}
        <form action="/photos" method="POST">
            {% csrf_token %}
            <label for="artist">Artist : </label>
            <input type="text" name="artist">
            <input type="submit" value="Search">
        </form>
        {% block content %}{% endblock %}
    </body>
</html>

photos.html:

{% extends 'index.html' %}
{% block error %}
    {% if error %}
        <p> {{ error}} </p>
    {% endif %}
{% endblock %}

{% block content %}
    {% if photos %}
        {% for photo in photos %}
            {{ photo }}
        {% endfor %}
    {% endif %}
{% endblock%}

url.py:

urlpatterns = patterns('',
    (r'', index),
    (r'^time/$', current_datetime),
    (r'^photos/(\w+)$', photos)
)

I even tried by adding {% csrf_token %}, but no luck

Thank you

UPDATE
I see these in the logs

UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value.  This is usually caused by not using RequestContext.
  warnings.warn("A {% csrf_token %} was used in a template, but the context did not provide the value.  This is usually caused by not using RequestContext.")  

This came after adding context_instance=RequestContext(request) **to render_to_response()**

0

7 Answers 7

9

add context_instance=RequestContext(request) to every view that you will use a form inside it:

return render_to_response('index.html', {}, context_instance=RequestContext(request) )


return render_to_response('photos.html', {'photos': photos}, context_instance=RequestContext(request) )
Sign up to request clarification or add additional context in comments.

1 Comment

...or if you use Django 1.3, you can use a shorter version of this: render(request, 'index.html', {}) docs.djangoproject.com/en/1.3/topics/http/shortcuts/#render
5

Supposing you are using a fairly recent version of Django (1.3/1.4/dev) you should follow these steps :

  • In settings.py, Add the middleware django.middleware.csrf.CsrfViewMiddleware to the MIDDLEWARE_CLASSES list.
  • In your template, use the {% crsf_token %} in the form.
  • In your view, ensure that the django.core.context_processors.csrf context processor is used either by :
    • use RequestContext from django.template
    • directly import the csrf processor from from django.core.context_processors

Examples

from django.template import RequestContext
from django.shortcuts import render_to_response

def my_view(request):
    return render_to_response('my_template.html', {}, context_instance=RequestContext(request))

or

from django.core.context_processors import csrf
from django.shortcuts import render_to_response

def my_view(request):
    c = {csrf(request)}
    return render_to_response('my_template.html', c)

References

(exhaustive post for posterity and future viewers)

Comments

3

A number of things to troubleshoot here:

  • Please load your "index" page in a web browser, do "View Source", and check if the {% csrf_token %} is being expanded. It should be replaced with an <input> tag. If that's not happening, then you have problems with your index page. If it is being replaced correctly, then you have problems with your photos page.

  • The POST URL in index.html doesn't match any of the patterns in urls.py. Your urls.py seems to expect the search term to be part of the URL, but it's not - you're sending it as a HTTP POST parameter. You need to access it via request.POST.

2 Comments

Good points. It is usually better to do searches with a GET instead of a POST method as they can then be bookmarked. So I would suggest changing the template, over changing the view. One or the other does need to be changed.
Actually , this is the Ultimate solution! I ran across a lot of articles mentioning this problem, but only this one point out the truth. Please render the index page with Requestcontext as well.
2

Check in the settings, if you have this middleware:

'django.middleware.csrf.CsrfViewMiddleware'

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

1 Comment

and the context processor 'django.core.context_processors.csrf'?
1

You may need to explicitly pass in a RequestContext instance when you use render_to_response in order to get the CSRF values for that template tag.

http://lincolnloop.com/blog/2008/may/10/getting-requestcontext-your-templates/

Comments

0

Try using the @csrf_protect decorator:

from django.views.decorators.csrf import csrf_protect
from django.shortcuts import render_to_response

@csrf_protect
def photos(request,artist):
    if not artist:
        return render_to_response('photos.html', {'error' : 'no artist supplied'})
    photos = get_photos_for_artist(artist)
    if not photos:
        logging.error('Issue while getting photos for artist')
        return render_to_response('photos.html', {'error': 'no matching artist found'})
    return render_to_response('photos.html', {'photos': photos})  

4 Comments

Tried that, but it in that case doesn't seem to be calling photos function, logs say [06/Dec/2011 18:08:05] "GET / HTTP/1.1" 200 403 [06/Dec/2011 18:08:08] "POST /photos HTTP/1.1" 200 403
I guess you've seen this: "By default, a '403 Forbidden' response is sent to the user if an incoming request fails the checks performed by CsrfViewMiddleware. This should usually only be seen when there is a genuine Cross Site Request Forgery, or when, due to a programming error, the CSRF token has not been included with a POST form." from docs.djangoproject.com/en/dev/ref/contrib/csrf. It seems the CSRF-token is not properly transmitted somehow.
If you add csrf_protect to the index view?
I added @csrf_protect in both index and photos, but no luck! I am sure its programming error, but not sure where
-1

This worked for me:

{% csrf_token %} In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.

In views.py:

from django.template import RequestContext

...

...

...

return render_to_response("home.html", {}, context_instance=RequestContext(request))

1 Comment

Not sure how this answer adds something hasn't already been covered by already posted answers?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.