Django : CSRF verification failed even after adding {% csrf_token %} - python

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()**

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) )

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
csrf in Django 1.3 or csrf in Django 1.4
RequestContext in Django 1.3 or RequestContext in Django 1.4
(exhaustive post for posterity and future viewers)

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.

Check in the settings, if you have this middleware:
'django.middleware.csrf.CsrfViewMiddleware'
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/

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/

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})

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))

Related

Getting no reverse match at /post in django

I have been facing this issue. And I have a url name post-page-detail but then also getting error please
See the error screenshot below.
My html page
<a href="{% url "post-detail-page" slug=post.slug %}">
<h2>{{post.tractor_company}} || {{post.tractor_model}}</h2>
<pre><h5>{{post.implimentaion}}</h5>
{{post.farmer}}
Uplode Date : {{post.date}}</pre>
</a>
</div>
URLs.py
from . import views
urlpatterns = [
path("",views.starting_page,name = "starting-page"),
path("posts",views.posts,name = "post-page"),
path("posts/<slug:slug>",views.post_detail,name="post-detail-page"),
]
View.py
from django import forms
from django.contrib.auth.models import User
from django.shortcuts import render, redirect ,get_object_or_404
from .models import Post, Farmer
# Create your views here.
from django.http import HttpResponseRedirect
# Create your views here.
def starting_page(request):
return render(request,"tractor/index.html")
def posts(request):
qs = Post.objects.all()
context = {"posts":qs}
return render(request,"tractor/all-post.html",context)
def add_post(request):
pass
def post_detail(request,slug):
indentified_post = get_object_or_404(Post,slug=slug)
return render(request,"blog/post-detail.html",{'post':indentified_post})
i am iterating through posts and using the post-detail.html page
all-post.html.
{% load static %}
{% block title %}
All Tractors
{% endblock %}
{% block content%}
<section id="all_events">
<br>
<h1 style="text-align:center;">All Tractors</h1>
<ul>
{% for post in posts %}
<br>
{% include "tractor/includes/singlePost.html" %}
{% endfor %}
</ul>
</section>
{% endblock %}```
Try this:
{% url 'post-detail-page' post.slug as post_detail_url %}
<a href="{{ post_detail_url }}">
Let me know if it worked.

python crash course 19-1 edit posts not working

This is the error I get when clicking on Edit post under any one of the posts. Would appreciate any help as all this django stuff is confusing me but trying my best to learn. My new post function works and clicking blog/posts to go to the overview page for the blog or to look at all the posts works as well.
NoReverseMatch at /edit_post/1/
Reverse for 'posts' with arguments '(1,)' not found. 1 pattern(s) tried: ['posts/$']
Error during template rendering
In template C:\Users\seng\Desktop\Python projects\c19\nineteen_one\blogs\templates\blogs\base.html, error at line 0
urls.py
"""Defines url paterns for blogs"""
from django.urls import path
from . import views
app_name = 'blogs'
urlpatterns =[
#Home page
path('', views.index, name='index'),
# Page that shows all posts/
path('posts/', views.posts, name='posts'),
#Page for adding a new blogpost
path('new_post/', views.new_post, name='new_post'),
#Page for editing a post
#maybe remove the id?
path('edit_post/<int:post_id>/', views.edit_post, name='edit_post'),
]
views.py
from django.shortcuts import render, redirect
from .models import BlogPost
from .forms import BlogPostForm
# Create your views here.
def index(request):
"""The home page for blogs"""
return render(request, 'blogs/index.html')
def posts(request):
"""Show all blogposts"""
posts = BlogPost.objects.order_by('date_added')
context = {'posts': posts}
return render(request, 'blogs/posts.html', context)
def new_post(request):
"""Add a new blogpost"""
if request.method != 'POST':
#No data submitted; create a blank form.
form = BlogPostForm()
else:
#POST data submitted, process data
form = BlogPostForm(data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:posts')
#Display a blank or invalid form
context = {'form': form}
return render(request, 'blogs/new_post.html', context)
def edit_post(request, post_id):
"""Edit existing post"""
post = BlogPost.objects.get(id=post_id)
if request.method != "POST":
#Initial request, pre-fill form with the current post
form = BlogPostForm(instance=post)
else:
#Post data submitted, process data
form = BlogPostForm(instance=post, data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:posts', post_id=post.id)
context = {'post':post, 'form':form}
return render(request, 'blogs/edit_post.html', context)
forms.py
from django import forms
from .models import BlogPost
class BlogPostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['text', 'title']
labels = {'text':'This is the text box', 'title' :"Title here"}
edit_post.html
{% extends "blogs/base.html" %}
{% block content %}
<p>{{ post }}</p>
<p>Edit post:</p>
<form action="{% url 'blogs:edit_post' post.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save changes</button>
</form>
{% endblock content %}
posts.html
{% extends "blogs/base.html" %}
{% block content %}
<p>Posts</p>
<ul>
{% for post in posts %}
<li>
<p>{{ post }}</p>
<p>
Edit post
</p>
</li>
{% empty %}
<li>No posts have been added yet.</li>
{% endfor %}
</ul>
Add a new post
{% endblock content %}
new_post.html
{% extends "blogs/base.html" %}
{% block content %}
<p>Add a new post:</p>
<form action="{% url 'blogs:new_post' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Add post</button>
</form>
{% endblock content %}
The issue is with this line in edit_post.html:
<p>{{ post }}</p>
If you are editing the post with id 1, then this link is to the url /posts/1. But that has no match in your urls.py file.
Either you need to remove the post.id parameter from the link, or create a view and a corresponding path in urls.py for this link.

Django NoReverseMatch Error during Template Rendering

I am setting up a simple blog site with Django, and run into this error when trying to link to a page that allows users to edit existing blog posts.
Reverse for 'edit_post' with arguments '('',)' not found. 1 pattern(s) tried: ['edit_post/(?P<title_id>[0-9]+)/$']
If I understand this error correctly, it means that Django can't find a urlpattern that matches the url being requested. To my eyes I have the urlpattern set up correctly, but I still get the error.
The link in question appears on the text.html template, which is the template that displays the text of a particular blog post.
Here is the relevant code:
urls.py
"""Defines URL patterns for blogs."""
from django.urls import path
from . import views
app_name = 'blogs'
urlpatterns = [
# Home page, shows all posts in chronological order.
path('', views.index, name='index'),
# A page to show the text of a specific post.
path('text/<int:title_id>/', views.text, name='text'),
# Page for adding a new post.
path('new_post/', views.new_post, name='new_post'),
# Page for editing a post.
path('edit_post/<int:title_id>/', views.edit_post, name='edit_post'),
]
views.py
from django.shortcuts import render, redirect
from .models import BlogPost
from .forms import BlogPostForm
def index(request):
"""The home page for blogs, shows all posts."""
titles = BlogPost.objects.order_by('date_added')
context = {'titles': titles}
return render(request, 'blogs/index.html', context)
def text(request, title_id):
"""Show a single post title and its text."""
title = BlogPost.objects.get(id=title_id)
text = title.text
context = {'title': title, 'text': text}
return render(request, 'blogs/text.html', context)
def new_post(request):
"""Add a new post."""
if request.method != 'POST':
# No data submitted; create a new form.
form = BlogPostForm()
else:
# POST data submitted; process data.
form = BlogPostForm(data=request.POST)
if form.is_valid():
new_post = form.save(commit=False)
new_post.save()
return redirect('blogs:index')
# Display a blank or invalid form.
context = {'form': form}
return render(request, 'blogs/new_post.html', context)
def edit_post(request, title_id):
"""Edit an existing post."""
post = BlogPost.objects.get(id=title_id)
if request.method != 'POST':
# Initial request: pre-fill form with the current post.
form = BlogPostForm(instance=post)
else:
# Post data submitted; process data.
form = BlogPostForm(instance=post, data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:index')
context = {'post': post, 'form': form}
return render(request, 'blogs/edit_post.html', context)
index.html (this is the homepage for the blog)
{% extends "blogs/base.html" %}
{% block content %}
<p>Blog is a generic site for a blogger to post content for their audience.</p>
<p>Posts</p>
<ul>
{% for title in titles %}
<li>
{{ title }}
</li>
{% empty %}
<li>No posts have been added yet.</li>
{% endfor %}
</ul>
Create a new post
{% endblock content %}
text.html (this page displays the text content of a particular post, and also the link to edit the post)
{% extends "blogs/base.html" %}
{% block content %}
<p>Title: {{ title }}</p>
<p>{{ text }}</p>
Edit post
{% endblock content %}
edit_post.html (this page should display the existing post and allow it to be edited)
{% extends "blogs/base.html" %}
{% block content %}
<p>Edit post:</p>
<p>Title:</p>
<form action="{% url 'blogs:edit_post' title.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save changes</button>
</form>
{% endblock content %}
How the edit_post function in views.py should work (in theory) is to create an instance based upon the post's title id, and then allowing the user to edit it and save changes.
I'm not sure where I'm going wrong here and any suggestions are greatly appreciated.
The name of the post object you pass to the template, is not title, but post:
{% extends "blogs/base.html" %}
{% block content %}
<p>Edit post:</p>
<p>Title:</p>
<form action="{% url 'blogs:edit_post' post.pk %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save changes</button>
</form>
{% endblock content %}
If you use title.id, it will not find that variable, and thus this will be resolved to the empty string. If you use post.id, or post.pk, it will resolve to the .id field, or primary key of the post object.

Django search page

I'm trying to make a website that lets visitors search for books using another search engine. I have a script that takes a query, and returns some HTML with the results of the search, but I'm struggling to make a front end for this. I am using django because it seemed like the best option when I started, but now I am going in circles and I can't figure out how to make this thing - I'm just getting overwhelmed because the different tutorials and documentation that I'm reading all go into the advanced stuff before I can get the basic thing working.
Do I need separate search and results templates? Right now I'm getting the error The view book_search.views.search didn't return an HttpResponse object. It returned None instead.
How can I fix this error and/or design this whole thing better?
Here's what I have so far (the script that returns the results in html is pull.py):
The views and urls are from inside the book_search app.
views.py:
from django.shortcuts import render
from django.http import HttpResponse
from . import pull
from .forms import SearchForm
def index(request):
return HttpResponse("Welcome to the index page")
def test_search(request):
context = {'query': 'test query'}
return render(request, 'book_search/search.html', context)
def search(request):
if request.method == "GET":
form = SearchForm(request.GET)
if form.is_valid():
query = form.cleaned_data['query']
results = pull.main(query)
context = {'query': query, 'form': form, 'results': results}
return render(request, 'book_search/results.html', context)
apps.py:
from django.apps import AppConfig
class BookSearchConfig(AppConfig):
name = 'book_search'
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('index', views.index, name='index'),
path('test', views.test_search, name='test_search'),
path('', views.search, name='search'),
]
forms.py:
class SearchForm(forms.Form):
query = forms.CharField(label='Search', max_length=200)
template base.html:
<html>
<head>
</head>
<body>
<form method="GET" action="/search/">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
{% block content %}{% endblock %}
</body>
</html>
template results.html:
{% block content %}
{% results %}
{% endblock content %}
Since we guessed that form isn't valid (because no POST handler - you do not send anything to the form) and wrong indentation gives None response, now you can fix reference before assignment:
def search(request):
if request.method == "GET":
form = SearchForm()
context = {'form': form}
elif request.method == "POST":
form = SearchForm(request.POST)
if form.is_valid():
query = form.cleaned_data['query']
results = pull.main(query)
context = {'query': query, 'form': form, 'results': results}
return render(request, 'book_search/results.html', context)
and render errors in results.html template by putting this:
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}

Django authentication system

i'm using the django built in authentication system and in my login template i have this code :
login.html:
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
{% if user.is_authenticated%}
you are already logged in
{% else %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endif %}
{% endblock %}
but what i really want to do is to redirect the user to the home page if he tries to access login page while already logged in, but i am new to django so i don't know how to do that.
For django>=1.11 you can set redirect_authenticated_user parameter to True in its url in url_patterns to do the redirect, like this:
from django.contrib.auth import views as auth_views
urlpatterns = [
url(r'^login/', auth_views.LoginView.as_view(redirect_authenticated_user=True), name='login'),
]
read the document for more information.
and also set LOGIN_REDIRECT_URL in your setting file to your index url or its name:
LOGIN_REDIRECT_URL = '/index/'
In your `settings.py' add this:
LOGIN_REDIRECT_URL = 'index'
if the url name of your index is 'index', else put the correct url name
You can do it in your views.py file.
def login(request):
if request.method =="get":
if request.user.is_authenticated:
return render(// youre code)

Categories