I want to realize a login for my site. I basically copied and pasted the following bits from the Django Book together. However I still get an error (CSRF verification failed. Request aborted.), when submitting my registration form. Can somebody tell my what raised this error and how to fix it?
Here is my code:
views.py:
# Create your views here.
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
return HttpResponseRedirect("/books/")
else:
form = UserCreationForm()
return render_to_response("registration/register.html", {
'form': form,
})
register.html:
<html>
<body>
{% block title %}Create an account{% endblock %}
{% block content %}
<h1>Create an account</h1>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Create the account">
</form>
{% endblock %}
</body>
</html>
I was having the exact same issue - and Blue Peppers' answer got me on the right track. Adding a RequestContext to your form view fixes the problem.
from django.template import RequestContext
and:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
return HttpResponseRedirect("/books/")
else:
form = UserCreationForm()
c = {'form': form}
return render_to_response("registration/register.html", c, context_instance=RequestContext(request))
This fixed it for me.
I'm using Django 1.2.3, I had a few intermittent problems:
Things to do:
Ensure the csrf token is present in your template:
<form action="" method="post">{% csrf_token %}
Use a RequestContext:
return render_to_response('search-results.html', {'results' : results}, context_instance=RequestContext(request) )
Make sure you use a RequestContext for GETs as well, if they are handled by the same view function, and render the same template.
i.e:
if request.method == 'GET':
...
return render_to_response('search-results.html', {'results':results}, context_instance=RequestContext(request) )
elif request.method == 'POST':
...
return render_to_response('search-results.html', {'results':results}, context_instance=RequestContext(request))
not:
if request.method == 'GET':
...
return render_to_response('search-results.html', {'results':results})
elif request.method == 'POST':
...
return render_to_response('search-results.html', {'results':results}, context_instance=RequestContext(request))
Ensure 'django.middleware.csrf.CsrfViewMiddleware' is listed in your settings.py
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
Assuming you're on Django 1.2.x, just add this before {{form.as_p}}:
{% csrf_token %}
And to understand WHY, check out the CSRF docs
You need to add csrf(request) to your context.
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.core.context_processors import csrf
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
return HttpResponseRedirect("/books/")
else:
form = UserCreationForm()
con = {'form': form}
con.update(csrf(request))
return render_to_response("registration/register.html", con)
You might need to turn your context into a Context object for this, not a dict, but the principle is sound.
Add these 2 middlewares to the settings file if you don't want to add {% csrf_token %} to each form.
MIDDLEWARE_CLASSES = (
#...
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.csrf.CsrfResponseMiddleware',
)
Later answer.
Now render can use instead of context_instance=RequestContext(request)
from django.shortcuts import render
return render(request, "registration/register.html", {
'form': form,
})
Try removing the following line from your settings.py's MIDDLEWARE list if you intend to use the {% csrf_token %}:
'django.middleware.csrf.CsrfViewMiddleware',
Worked for me......
Related
I'm having problems deleting a user, where the authenticated user can delete their own account.
But what happens is that the page just refreshes, in the same template and returning '200 ok from POST'
[06/Aug/2022 11:46:33] "POST /members/profile/ HTTP/1.1" 200 4998
members.views.profiles.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
#login_required(login_url="/accounts/login/")
def profile(request):
template_name = "members/profile.html"
context = {}
return render(request, template_name, context)
def profile_delete(request, pk):
user_profile = User.objects.filter(pk=pk)
template_name = "members/profile_delete.html"
context = {
"user_profile": user_profile,
},
if request.method == "POST":
user_profile.delete()
return render(request, template_name, context)
return render(request, template_name, context)
members.urls.py
from django.urls import path
from allauth.account import views as allauth_views
from . import views
app_name = "members"
urlpatterns = [
path("login/", allauth_views.LoginView.as_view(), name="login"),
path("logout/", allauth_views.LogoutView.as_view(), name="logout"),
path("profile/", views.profile, name="profile"),
path("profile/<int:pk>/delete/", views.profile_delete, name="profile_delete"),
]
profile.html
<div>
<form method="POST">
{% csrf_token %}
<p>Are you sure you want to delete <strong>{{ user | title }}</strong> ?</p>
<button class="btn btn-danger" href="{% url 'members:profile_delete' user.pk %}" type="submit">
Delete
</button>
</form>
</div>
Solution:
views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
#login_required(login_url="/accounts/login/")
def profile(request):
template_name = "members/profile.html"
context = {}
return render(request, template_name, context)
def profile_delete(request, pk):
user_profile = get_object_or_404(User, pk=pk)
user_profile.delete()
template_name = "members/profile_delete.html"
context = {}
return render(request, template_name, context)
When you're pressing your button the server sends a GET request, try changing the logic in your function, instead of:
if request.method == "POST":
Use:
if request.method == "GET":
You should use get_object_or_404 for querying single user's profile and then delete it, currently filter() makes no sense, so:
user_profile=get_object_or_404(User,pk=pk)
Note: you should always return HttpResponseRedirect after dealing with POST data, the tip is not specific to Django, it's a good web practice in general.
form.save() not working my form.save for updating data isnt working when i try to update my post it shows the original unedited post it dosent save the updated version.i donnt know whats causing the error idk if its views or anything in template if anyone could help i will be very grateful please help.
here is the code:
views.py
from django.shortcuts import render
from django.shortcuts import HttpResponseRedirect
from .models import Post
from .forms import PostForm
def post_list(request):
posts = Post.objects.all()
context = {
'post_list': posts
}
return render(request, "posts/post_list.html", context)
def post_detail(request, post_id):
post = Post.objects.get(id=post_id)
context = {
'post': post
}
return render(request, "posts/post_detail.html", context)
def post_create(request):
form = PostForm(request.POST or None)
if form.is_valid():
form.save()
return HttpResponseRedirect('/posts')
context = {
"form": form,
"form_type": 'Create'
}
return render(request, "posts/post_create.html", context)
def post_update(request, post_id):
post = Post.objects.get(id=post_id)
form = PostForm(request.POST or None, instance=post)
if form.is_valid():
form.save()
return HttpResponseRedirect('/posts')
context = {
"form": form,
"form_type": 'Update'
}
return render(request, "posts/post_update.html", context)
def post_delete(request, post_id):
post = Post.objects.get(id=post_id)
post.delete()
return HttpResponseRedirect('/posts')
urls.py
from django.urls import path
from .views import post_list, post_detail, post_create, post_update, post_delete
urlpatterns = [
path('', post_list),
path('create/', post_create),
path('<post_id>/', post_detail),
path('<post_id>/update', post_update),
path('<post_id>/delete', post_delete),
]
post_update.html
<h1>welcome to post {{ form_type }}</h1>
<form method="POST" action=".">
{% csrf_token %}
<p>{{ form.as_p }}</p>
<button type="submit">{{ form_type }}</button>
</form>
action="." takes you from <post_id>/update to <post_id>/. You can fix this a few ways:
Change it to action="", which will submit from <post_id>/update to <post_id>/update.
Add a slash to the URL, i.e. path('<post_id>/update/', ...). Then action="." will submit from <post_id>/update/ to <post_id>/update/
Use the {% url %} tag instead of hardcoding the action. In your case there's a few changes you'd need to make, so I'll leave that as a challenge for you. The docs on reversing URLs should help.
I'm new to django and trying to create my first app and I think I might need some little help :)
I have a ModelForm on a site to submit and want to show the data on the same page. I'm having trouble to set up two functions on the same page, I think i might have to use a class and set it in urls.py but I'm not able to make it work :( the code looks like this:
forms.py:
from django import forms
from .models import Eintrag
class NameForm(forms.ModelForm):
class Meta:
model = Eintrag
fields = ['Anmeldung', 'Essen']
urls.py
from django.urls import path
from . import views
app_name = 'form'
urlpatterns = [
path('', views.get_name, name='form'),
]
views.py
from django.shortcuts import render
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from .forms import NameForm
from .models import Eintrag
#login_required()
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
eintrag = form.save(commit=False)
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
eintrag.Name = request.user # Set the user object here
eintrag.pub_date = timezone.now() # Set the user object here
eintrag.save()
return render(request, 'form/name.html', {'form': form})
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'form/name.html', {'form': form})
def post_list(request):
posts = Eintrag.objects.all()
return render('form/post_list.html', {'posts': posts})
name.html
...
{% include "form/post_list.html" %}
<form action="/form/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
...
post_list.html
{% for post in posts %}
{{ post }}
{% endfor %}
So the problem is in urls.py only get_name is handled and I'm clueless how I should include post_list. I rather not want to use different url's, do I have to?
Thanks for any help and advice!
You don't need a separate URL or view for the list. Just include the queryset in the context of your get_name view.
posts = Eintrag.objects.all()
return render(request, 'form/name.html', {'form': form, 'posts': posts})
with [Class Based View] it would be better.
But with your view, you can send multiple data via context.
#login_required()
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
''' codes '''
eintrag.save()
return HttpResponseRedirect(request.path) # generate an empty form
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
posts = Eintrag.objects.all() # the queryset is here, and sent via context
return render(request, 'form/name.html', {'form': form,'posts':posts})
I your html remain the same, but keep your form action='' empty
{% include "form/post_list.html" %}
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
The form field won't show up in the browser. There is only the submit button showing up.
views.py code:
def vote(request, pk):
# check if request is post
if request.method == 'POST':
# create a form and populate it with data from request
form = forms.Vote(request.POST)
if form.is_valid():
fact = Fact.objects.get(pk=pk)
fact.votes += int(form.cleaned_data['vote'])
fact.save()
return HttpResponseRedirect(reverse(
'facts:detail',
args=(pk,)
))
else:
form = forms.Vote()
return render(request, 'facts/fact_detail.html', {'form': form})
template(fact_detail.html) code:
<form method='POST'>
{% csrf_token %}
{{ form }}
<input type="submit" value="vote" />
</form>
Form class(forms.py) code:
VOTE_CHOICES = [
(1, 'upvote'),
(0, 'downvote')
]
class Vote(forms.Form):
vote = forms.ChoiceField(choices=VOTE_CHOICES, widget=forms.RadioSelect())
In views.py for the vote method initialize the form variable locally, before passing it as a parameter.
def vote(request, pk):
form=""
//rest of the code//
return render(request, 'facts/fact_detail.html', {'form': form})
I recommend check generic editing views from django documentation I think it has the solution
[ https://docs.djangoproject.com/en/1.11/ref/class-based-views/generic-editing/#createview][1]
I am getting this error when trying to implement csrf in django.
Forbidden (403)
CSRF verification failed. Request aborted.
Help
Reason given for failure:
CSRF token missing or incorrect. (and bla bla bla)
My Views.py shows following:
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.core.context_processors import csrf
from django.contrib.auth.forms import UserCreationForm
def login(request):
c = {}
c.update(csrf(request))
return render_to_response('login.html', c)
def auth_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect('/accounts/loggedin')
else:
return HttpResponseRedirect('/accounts/invalid')
def loggedin(request):
return render_to_response('loggedin.html',{'full_name':request.user.username})
def invalid_login(request):
return render_to_response('invalid_login.html')
def logout(request):
auth.logout(request)
return render_to_response('logout.html')
def register_user(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
args ={}
args.update(csrf(request))
args['form'] = UserCreationForm()
return render_to_response('register.html')
def register_success(request):
return render_to_response('register_success.html')
My register.html reflects following:
{% extends 'base.html' %}
{% block content %}
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{ form }}
<input type="submit" value="Register"/>
</form>
{% endblock %}
In urls.py:
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^articles/', include('article.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^accounts/login/$', 'django_test.views.login'),
url(r'^accounts/auth/$', 'django_test.views.auth_view'),
url(r'^accounts/logout/$', 'django_test.views.logout'),
url(r'^accounts/loggedin/$', 'django_test.views.loggedin'),
url(r'^accounts/invalid/$', 'django_test.views.invalid_login'),
url(r'^accounts/register/$', 'django_test.views.register_user'),
url(r'^accounts/register_success/$', 'django_test.views.register_success'),
)
Please advise. I got cookies enabled in browser.
In register.html you need to add csrf token within <form> </form> like this: {% csrf_token %}, hopefully it will resolve the problem.
This might not be the best practice but you can add:
#csrf_exempt
Just above the functions in the view.py file.
See example in django-rest-framework tutorial:
Writing regular Django views