I have tried all I can gather from the forums, still need help:
I keep getting the CSRF token missing or incorrect error when I submit a form. It used to be working fine and then I made some changes and now I cant get back.. I am using {% csrf_token %} and RequestContext. I have tried using reverse, i checked the settings.py middleware for the csrf middleware, tried restarting the server, tried using HttpResponse instead of HttpResponseRedirect and template.render(), tried a url path instead of the {% url %} tag. In other parts of my project I am not even using RequestContext and it works fine..
signup_page.html:
<p>Sign Up Below
</p>
<form action={% url 'signup_page' %} method="post">
{% csrf_token %}
....
Email
<input type="email" name="email" required="true"><br><br>
<input type="submit" value="POST">
</form>
views.py
def signup_page(request):
template = loader.get_template('user_app/signup_page.html')
if request.method == "POST":
...
email = request.POST['email']
kwargs = {
'username':username, 'password':password, 'first_name':first_name,
'last_name':last_name, 'email':email
}
new_user = User.objects.create(**kwargs)
new_user.save()
context = {
'text':"POST", 'first_name':first_name
}
return HttpResponseRedirect(render('signup_page', context, context_instance =RequestContext(request)))
else:
return HttpResponse(template.render(RequestContext(request)))
urls.py:
from django.conf.urls import url
from user_app.views import signup_page, profile
urlpatterns = [
url(r'^signup', signup_page, name="signup_page"),
url(r'^profile', profile, name="profile")
]
from django.shortcuts import render
#create your views here
def your_function(request):
#do whatever you want here...
context = {'any_data': 'you_want_to_send'}
return render(request,'your.html',context)
Add csrf decorator. Reference: https://docs.djangoproject.com/en/1.10/ref/csrf/#module-django.views.decorators.csrf
from django.views.decorators.csrf import csrf_protect
#csrf_protect
def signup_page(request):
...
Related
I'm newbie and trying to do something pretty basic after reading the Django Doc Project Documentation, but can't seem to figure it out. I'm getting a user's name with a POST and trying to GET it and display it on the same page. I'm getting an error: hello() missing 1 required positional argument: 'greeting_id'
I'm using Django 2 and wondering if it could be something with the routing? I'm not exactly sure as I'm very new to MVC and Django.
Any help in the right direction would be greatly appreciated.
Here's my code so far:
Views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Greeting
# create hello view
def hello(request, greeting_id):
if request.method == 'POST':
if request.POST['firstname']:
greeting = models.Greeting()
greeting.firstname = request.POST['firstname']
greeting.save()
obj = models.Greeting.objects.get(pk=greeting_id)
context = {
'object': obj
}
return render(request, 'greetings/home.html', context)
return render(request, 'greetings/home.html')
Models.py
from django.db import models
# Create your models here.
class Greeting(models.Model):
firstname = models.CharField(max_length=100)
# returns post object in admin interface
def __str__(self):
return self.firstname
urls.py
from django.contrib import admin
from django.urls import path
from greetings import views #import greetings views into the url file
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', views.hello, name='hello'),
]
home.html
{% block content %}
<h2>Let's Say Hello!</h2>
<br/>
<br/>
<div>
<form method="POST" action="{% url 'hello' %}">
{% csrf_token %}
Enter your first name:
<br />
<input type="text" name="firstname" />
<br />
<br />
<input type="submit">
</form>
{{ object.firstname }}
</div>
{% endblock %}
Your view "hello" requires an parameter "greeting_id"
def hello(request, greeting_id):
These parameters are passed from the url routing to the view, for the view to work your url would have to look like this
path('hello/<int:greeting_id>/', views.hello, name='hello'),
Where is greeting_id supposed to be coming from?
I have a login form with POST method and when I submit the login data, it goes straight to the empty url and doesn't execute the login method in views.py. Ideally, after I submit the form in www.url.com/login via submit button, it should return a HttpResponse but instead, it takes me to www.url.com/
I am new to Django, I'd appreciate it if you could look into it. Thanks!
home.html
<center><h1>Welcome to my website</h1>
<form method='POST'> {% csrf_token %}
{{ form }}
<button type='submit' class='btn btn-default'>Submit</button>
</form>
</center>
urls.py
from django.contrib import admin
from django.urls import path
from .views import home, login
urlpatterns = [
path('', home),
path('login/', login),
path('admin/', admin.site.urls),
]
forms.py
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(widget=forms.TextInput(attrs={"class":"form-control", "placeholder":"Your username"}))
password = forms.CharField(widget=forms.PasswordInput(attrs={"class":"form-control", "placeholder":"Your password"}))
views.py
from django.contrib.auth import authenticate, login
from django.http import HttpResponse
from django.shortcuts import render
from .forms import LoginForm
def home(request):
context={
"form": "Test"
}
return render(request, "home.html", context)
def login(request):
login_form = LoginForm(request.POST or None)
context={
"form": login_form
}
if login_form.is_valid():
username = login_form.cleaned_data.get('username')
password = login_form.cleaned_data.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
#request.user.is_authenticated()
login(request, user)
return HttpResponse("You are now logged in")
else:
return HttpResponse('Error')
return render(request, "home.html", context)
First, you should set an attribute action in the form which set a url to send.
Second, a url value in action must be clear. It's not a matter of Django but HTML.
I'd like to recommend you to use absolute path. If you use relative path, a slash string would be added whenever you send a request.
<form action="/login/" method='POST'>
{% csrf_token %}
{{ form }}
<button type='submit' class='btn btn-default'>Submit</button>
</form>
This is because your form doesn't contain action, i.e. where should the POST call be made with the user credentials.
Try following change in home.html:
<center><h1>Welcome to my website</h1>
<form action="" method='POST'> {% csrf_token %}
{{ form }}
<button type='submit' class='btn btn-default'>Submit</button>
</form>
</center>
Following the answers before, it would be a good practice to use named patterns instead of fixed urls.
# urls
...
path('login/', login, name='login'),
...
# template
<form action="{% url 'login' %}" method='POST'>
So if you change for example
login/
for
accounts/login/
You don't have to change the template as well.
urlpatterns = [
re_path('^$', home_page),
re_path('^admin/', admin.site.urls),
re_path('^register/$', register_page, name='register'),
re_path('^login/$', login_page, name='login'),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
I solved this by adding ^$to the beginning and end of the patterns.
Hello i can't make my form work. The button is displayed but the charfield never shows up. I tried to use a if statement with the "sent" parameter and it worked. I just followed the django doc. I did not find a solution in other posts.
Here is my forms.py:
from django import forms
class CharacterForm(forms.Form):
character_name = forms.CharField(label='Search', max_length=30)
views.py:
from django.shortcuts import render
from .forms import CharacterForm
def index(request):
return render(request, 'perso/pages/index.html')
def get_character(request):
character_name = ''
sent = False
if request.method == 'POST':
form = CharacterForm(request.POST)
if form.is_valid():
character_name = form.cleaned_data['character_name']
sent = True
else:
form = CharacterForm()
return render(request, 'perso/pages/index.html', {
'form': form,
'character_name': character_name,
'sent': sent
})
Perso is the name of the app, Urls.py in perso:
from django.conf.urls import url
from . import views
app_name = 'perso'
urlpatterns = [
url(r'^$', views.index, name="index"),
]
My form in template index of perso:
<form action="{% url "perso:index" %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Here is what appears in the browser:
<form action="/perso/" method="post">
<input type='hidden' name='csrfmiddlewaretoken' value='IWmBEknyibHw4LpvjnyfLWKcUOXLbw27RdHgR7GjhTDelCLGZ51QeF3y9wRyC0Mg' />
<input type="submit" value="Submit" />
</form>
The charfield is missing. No error in the console.
You have some anomaly in your code you missed out the template name argument in your render function. Provide the template name of your corresponding HTML file in the render function. You also missed providing default arguments of character_name and sent variable. See docs here
from django.shortcuts import render
from .forms import CharacterForm
def get_character(request):
character_name = ''
sent = False
if request.method == 'POST':
form = CharacterForm(request.POST)
if form.is_valid():
character_name = form.cleaned_data['character_name']
sent = True
else:
form = CharacterForm()
return render(request, 'template_name.html', {
'form': form,
'character_name': character_name,
'sent': sent
})
You have made mistake to not make urls.py pattern for the function in views.py that is setting the form in the template
from django.conf.urls import url
from . import views
app_name = 'perso'
urlpatterns = [
url(r'^$', views.index, name="index"),
url(r'^character$', views.get_character, name="character"),
]
Also you need correction in your template in your post request URL link
<form action="{% url "perso:character" %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Now your form will be avaliable at http://localhost:8000/character
I have my page deployed at http://example.com. I also have my django application deployed at http://example.com/djangoapp.
I'm using Apache 2.2 with this configuration (/etc/apache2/apache2.conf): WSGIPythonPath /home/brian/djangoprojects/djangoapp.
I also added the line WSGIScriptAlias /djangoapp /home/brian/djangoprojects/djangoapp/djangoapp/wsgi.py to the default Apache Virtual Host file and it works really nice.
However, in my application I'm using the auth module to register and login users, and have some problems with it. Sometimes I got redirected to the main page, http://example.com/, sometimes to http://example.com/register instead of http://example.com/djangoapp/register.
Changes I made in my project:
Edited settings.py and added:
LOGIN_URL = '/djangoapp/accounts/login/'
USE_X_FORWARDED_HOST = True
FORCE_SCRIPT_NAME = '/djangoapp'
SUB_SITE = "/djangoapp"
My urls.py file looks like this:
from django.conf.urls import include, url
from django.contrib import admin
from djangoapp import views
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^$', 'django.contrib.auth.views.login'),
url(r'^logout/$', views.logout_page),
url(r'^accounts/login/$', 'django.contrib.auth.views.login'), # If user is not login it will redirect to login page
url(r'^register/$', views.register),
url(r'^register/success/$', views.register_success),
url(r'^home/$', views.home),
]
And here's my views.py file:
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout
from django.contrib.auth.models import User
from django.views.decorators.csrf import csrf_protect
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.template import RequestContext
from djangoapp.forms import RegistrationForm
#csrf_protect
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
email=form.cleaned_data['email']
)
return HttpResponseRedirect('register/success/')
else:
form = RegistrationForm()
variables = RequestContext(request, {
'form': form
})
return render_to_response(
'registration/register.html',
variables,
)
def register_success(request):
return render_to_response(
'registration/success.html',
)
def logout_page(request):
logout(request)
return HttpResponseRedirect('/')
#login_required
def home(request):
return render_to_response(
'home.html',
{'user': request.user}
)
This is the production server and it's available online. I tried to use a work-around, but with no effect. I simply changed links on page and added djangoapp at the beginning, for instance:
{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block head %}Login{% endblock %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post" action=".">{% csrf_token %}
<table border="0">
<tr><th><label for="id_username">Username:</label></th><td>{{ form.username }}</td></tr>
<tr><th><label for="id_password">Password:</label></th><td>{{ form.password }}</td></tr>
</table>
<input type="submit" value="Login" />
<input type="hidden" name="next" value="/home" />
</form>
Register
{% endblock %}
And I tried to change Register to Register but I'm sure there's got to be a smarter solution. Any advice?
You need to use the {% url %} tag and the reverse function consistently. So:
Register
and
return HttpResponseRedirect(reverse('register_success'))
For this to work you also need to give your URL patterns names:
url(r'^register/$', views.register, name="register"),
url(r'^register/success/$', views.register_success, name="register_success"),
Aso, as I said in the comment, you do not need to set FORCE_SCRIPT_NAME yourself.
Forbidden (403) CSRF verification failed.
Request aborted. Reason given for failure: CSRF cookie not set.
I get the above error and there are a few solutions out there, but not for class-based views. What should def get_context_data(self, **kwargs): be returning? Below the message, it suggests 4 solutions, and the following suggestion catches my attention. So perhaps I should be returning a RequestContext somehow?
The view function uses RequestContext for the template, instead of Context.
I'm already using {% csrf_token %}, cookies are enabled and I have it included in the middleware. So I think I may be returning the wrong thing but all the other examples around here use function views.
My template snippet:
{% if not user.is_authenticated %}
<form id="login" method="post" action="login">{% csrf_token %}
<input type="text" name="username" value="" placeholder="Email">
<input type="password" name="password" value="" placeholder="Password">
<input type="submit" name="commit" value="Login">
</form>
{% elif user.is_authenticated %}
<p>Welcome, {{ user.get_displayname }}.</p>
{% endif %}
My urls.py:
from django.conf.urls import patterns, include, url
from mainapp.views import Index, LoginResponse
from django.contrib import admin
admin.autodiscover()
from mainapp import views
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^$', Index.as_view()),
url(r'^login$', LoginResponse.as_view()),
)
My LoginResponse class view:
class LoginResponse(TemplateView):
template_name = 'index.html'
def get_context_data(self, **kwargs):
context = super(LoginResponse, self).get_context_data(**kwargs)
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
return context
For CSRF verification there is no difference between function based and class based views. This verification is done at middleware level.
So show your template and urls.py please.