I am new to Django. I am creating a signup page. But I am having an unexpected MultiValueDictKeyError with Exception value fname.
views.py:
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from django.contrib import auth
# Create your views here.
def signup(request):
if request.method == 'POST':
# User has and wants account now
if request.POST['password1'] == request.POST['password2']:
# Check if username already exists
try:
user = User.objects.get(username=request.POST['uname'])
return render(request, 'accounts/signup.html',{'error':'username already exist'})
# If username unoccupied
except User.DoesNotExist:
user = User.objects.create_user(fname = request.POST['fname'],lname = request.POST['lname'],email = request.POST['email'],uname = request.POST['uname'],password = request.POST['password1'])
# updating new user
auth.login(request,user)
return redirect('home')
else:
return render(request,'accounts/signup.html')
def login(request):
if request.method == 'POST':
#
user = auth.authenticate(username = request.POST['username'],password = request.POST['password'])
if user is not None:
auth.login(request,user)
return redirect('home')
else:
return render(request, 'accounts/login.html',{'error': 'username or password incorrect'})
else:
#
return render(request,'accounts/login.html')
def logout(request):
if request.method == 'POST':
auth.logout(request)
return redirect('home')
sign up page:
{% extends 'base.html'%}
{% block content %}
<div class="container-fluid" style="background-image: linear-gradient(to right, #1a1aff , #000099);padding: 10vh">
<div class="row">
<div class="col center" style="color: white;padding: 05vw">
<h1> Sign Up Now! </h1>
<br>
<h2> Become the part world's first personalized <br> Network <h2>
</div>
<div class="col-5 center container" style="color:black;padding: 02vw;background-color: white;">
<span>
<center>
<h1>Sign Up</h1>
</center>
<br>
</span>
<form action="{% url 'signup' %}" method="POST">
{% csrf_token %}
{% if error %}
<p style="color:red "> {{error}} </p>
{% endif %}
<h3>First Name</h3>
<input type="text" id="fname" name="firstname" placeholder="Your name..">
<br>
<h3>Last Name</h3>
<input type="text" id="lname" name="lastname" placeholder="Last Name">
<br>
<h3>Email</h3>
<input type="email" id="email" name="email" placeholder="Email Address">
<br>
<h3>Username</h3>
<input type="text" id="uname" name="uname" placeholder="Username">
<br>
<h3>Password</h3>
<input type="password" id="password" name="password1" placeholder="Password">
<br>
<h3>Confirm Password</h3>
<input type="password" id="password" name="password2" placeholder="Password">
<br>
<br>
<input type="submit" value="Sign Up Now">
</form>
</div>
</div>
</div>
enter code here
{% endblock %}
The field is firstname, not fname. This is why you should use Django forms rather than accessing the POST directly
Related
So, I've tried a couple of times to register and back to login. Always failed to log in except for superuser or admin. Already checked in Django admin that the user that I have registered already there.
There is no error message in the terminal when login or register a user. Except for the error message that I've created in views.py if log in unsuccessful.
So, let's take a look into my code. First views.py
from django.contrib.auth import authenticate, login, logout
def login_view(request):
if request.method == "POST":
# Attempt to sign user in
username = request.POST["username"]
password = request.POST["password"]
user = authenticate(request, username=username, password=password)
# Check if authenticate successful
if user is not None:
login(request, user)
return HttpResponseRedirect(reverse("index"))
else:
context = {
"message": "Invalid username and/or password"
}
return render(request, "page/login.html", context)
else:
return render(request, "page/login.html")
def register(request):
if request.method == "POST":
username = request.POST["username"]
email = request.POST["email"]
# Ensure password matches with password confirmation
password = request.POST["password"]
confirmation = request.POST["confirmation"]
if password != confirmation:
context = {
"message": "Both password must match"
}
return render(request, "page/register.html", context)
# Attempt to create new user
try:
user = User.objects.create_user(username)
user.save()
except IntegrityError:
context = {
"message": "Username already exist"
}
return render(request, "page/register.html", context)
login(request, user)
return HttpResponseRedirect(reverse("index"))
else:
return render(request, "page/register.html")
And below is the template both for log in and register.
<!-- Logintemplate -->
<div class="login-register">
<div class="head">
Log in to Explore
</div>
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
<div class="form-floating mb-3">
<input type="text" class="form-control" id="username" name="username" placeholder="Username"">
<label for="username">Username</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
<label for="password">Password</label>
</div>
<div class="d-grid gap-2">
<input class="btn btn-outline-success" type="submit" value="Login">
</div>
<div id="log-reg">
Sign Up
</div>
</form>
{% if message %}
<div class="alert alert-danger mt-4" role="alert">
{{ message }}
</div>
{% endif %}
</div>
<!-- Register template -->
<div class="login-register">
<div class="head">
Create your account
</div>
<form action="{% url 'register' %}" method="post">
{% csrf_token %}
<div class="form-floating mb-3">
<input type="text" class="form-control" autofocus type="text" name="username" id="username" placeholder="Username">
<label for="username">Username</label>
</div>
<div class="form-floating mb-3">
<input type="email" class="form-control" name="email" id="email" placeholder="name#example.com">
<label for="email">Email address</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
<label for="password">Password</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control" id="confirmation" name="confirmation" placeholder="Confirm Password">
<label for="confirmation">Password Confirmation</label>
</div>
<div class="d-grid gap-2">
<input class="btn btn-outline-success" type="submit" value="Register">
</div>
<div id="log-reg">
Already have an account? Log In here.
</div>
</form>
{% if message %}
<div class="alert alert-danger mt-4" role="alert">
{{ message }}
</div>
{% endif %}
</div>
Is there something I missed or action that I need to perform?
You create the user as follows:
user = User.objects.create_user(username)
This creates a user without a password which means your user would not be able to login. pass the username and password both to the create_user method:
user = User.objects.create_user(username=username, password=password)
Note: Use a form class to make forms in Django to perform validation and cleaning. For making a user use the
UserCreationForm
I have created a user and given him all the required data, but I cannot log into the page, I sure the email and password correct , but it gives me error in the information entered.
template:
<form action="" method="post" class="border rounded overflow-hidden p-5">
{% csrf_token %}
<h4 class="text-center py-3 title">Login </h4>
{% for message in messages %}
<div class="btn btn-sm btn-dark col-6" role="alert">
<h3 class="text-center"> {{ message }}</h3>
</div>
{% endfor %}
<div class="row">
<div class="form-group col-md-12 text-left px-0">
<label for="email">Email</label>
<input class="border rounded-2 p-3 bg-input " type="email" name="email" id="email" placeholder="Email ">
</div>
<div class="form-group col-md-12 text-left px-0">
<label for="password">Password </label>
<input class="border rounded-2 p-3 bg-input " type="password" class="form-control" id="password" name="password">
</div>
<button class="btn btn-sm btn-dark col-12 rounded-2 my-4 p-3" type="submit">Login </button>
</div>
</form>
my view:
from django.contrib.auth import authenticate,login
from django.shortcuts import render,redirect
from django.contrib.auth.models import auth,Group
from django.contrib import messages
from django.conf import settings
from django.contrib.auth.decorators import login_required
from .decorators import uthenticated_user
from app.models import *
# Create your views here.
#uthenticated_user
def login(request):
if request.method=='POST':
email=request.POST['email']
password=request.POST['password']
user=authenticate(request,email=email,password=password)
if user is not None:
login(request,user)
return redirect('user_home')
else:
messages.error(request,'There was a problem logging in. Check your email and password or create an account')
return redirect('login')
else:
return render(request,'registration/sign-in.html')
As i know, authenticate is only taking username and password. You can try to find username by email firstly and then authenticate him:
#uthenticated_user
def login(request):
if request.method=='POST':
email=request.POST['email']
password=request.POST['password']
# New code
try:
username = User.objects.get(email=email).username
except User.DoesNotExist:
username = None
user=authenticate(request,username=username,password=password)
if user is not None:
login(request,user)
return redirect('user_home')
else:
messages.error(request,'There was a problem logging in. Check your email and password or create an account')
return redirect('login')
else:
return render(request,'registration/sign-in.html')
I'm working on forget password page in which the user first have to answer the question for enabling the textfields for creating new password.
Here, I have two forms, One for security question and second for password and confirm password.
Following is my forms.py
from django import forms
from .models import SecurityQuestions
class PasswordForm(forms.Form):
password = forms.CharField(disabled=True, widget=forms.PasswordInput(attrs={'placeholder':'New Password'}))
password_confirm = forms.CharField(disabled=True, widget=forms.PasswordInput(attrs={'placeholder':'Re-enter Password'}))
def clean(self, *args,**kwargs):
password = self.cleaned_data.get('password')
password_confirm = self.cleaned_data.get('password_confirm')
if password and password_confirm:
if password != password_confirm:
raise forms.ValidationError('Password Mismatch')
return super(PasswordForm, self).clean(*args, **kwargs)
class PasswordVerificationForm(forms.Form):
question = forms.ModelChoiceField(queryset=SecurityQuestions.objects.all(), empty_label=None, widget=forms.Select(attrs={'class':'form-control','id': 'sectxt'}))
answer = forms.CharField(label='answer', widget=forms.TextInput(attrs={'placeholder':'Answer','id': 'anstxt'}))
Following is my views.py
from django.shortcuts import render, redirect
from .forms import PasswordForm, PasswordVerificationForm
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.hashers import make_password
from .models import SecurityQuestions
from django.contrib import messages
#login_required
#csrf_exempt
def password_reset(request):
form = PasswordForm(request.POST or None)
form1 = PasswordVerificationForm(request.POST or None)
if request.method == 'POST':
if request.POST.get("verify", False):
question = request.POST.get('question')
answer = request.POST.get('answer')
print("question",question)
print("answer",answer)
check = SecurityQuestions.objects.get(id=question) #id=1
print(check.answer)
if check.answer == answer:
messages.success(request, 'Enter Your New Password', 'alert-success')
form.fields['password'].disabled = False
form.fields['password_confirm'].disabled = False
else:
redirect('/')
messages.error(request, 'Incorrect Answer', 'alert-danger')
if request.POST.get("create", False):
if form.is_valid():
print("For Changing Password...")
password = form.cleaned_data.get('password')
request.user.password = make_password(password)
request.user.save()
return redirect('/')
else:
form = PasswordForm()
form1 = PasswordVerificationForm()
return render(request,"forget_password.html", {"form": form, "form1":form1})
Following is my forget_password.html
<div class="container">
<div class="main">
<div class="row justify-content-center">
<div class="col-md-4">
<div class="login-form">
<div class="row">
<div class="col-md-12">
<div class="login-title-holder">
<h4>Forgot Password</h4>
</div>
</div>
<form method="post">
<div class="form-group col-md-12">
<div class="input-group">
{{ form1.question | add_class:'form-control' }}
<span class="input-group-append">
<div class="input-group-text input-group-icon"><i class="fa fa-question" aria-hidden="true"></i></div>
</span>
</div>
</div>
<div class="form-group col-md-12">
<div class="input-group">
{{ form1.answer | add_class:'form-control' }}
<span class="input-group-append">
<div class="input-group-text input-group-icon "><i class="fa fa-comment" aria-hidden="true"></i></div>
</span>
</div>
</div>
<div class="col-md-12">
{% if messages %}
{% for message in messages %}
<div {% if message.tags %} class="alert {{ message.tags }} text-center"{% endif %}>
×
{{ message }}
</div>
{% endfor %}
{% endif %}
<input type="submit" name = "verify" formmethod="post" style="visibility: hidden;">
</div>
</form>
<form method="post">
<div class="form-group col-md-12">
<div class="input-group">
{{ form.password | add_class:'form-control' }}
<span class="input-group-append">
<div class="input-group-text input-group-icon"><i class="fa fa-key" aria-hidden="true"></i></div>
</span>
</div>
</div>
<div class="form-group col-md-12">
<div class="input-group">
{{ form.password_confirm | add_class:'form-control' }}
<span class="input-group-append">
<div class="input-group-text input-group-icon"><i class="fa fa-key" aria-hidden="true"></i></div>
</span>
</div>
</div>
<div class="col-md-12">
<div class="button-holder">
Cancel
<button class="login-btn" type="submit" formmethod="post" name="create">Create</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
If I enter the security answer first, based on the condition, if true, it enables the textfields for password and password_confirm.
But it's not creating the new password.
However, if I change the disabled = False in PasswordForm then it creating the new password successfully.
I want to know why it's not executing the code after the first form executes successfully.
Thanks!
You really should chain this into 2 urls, rather then trying 2 forms in one page. You can only submit one form and this is the problem you're facing. Once you have submitted the security question, you instantiate the form again with fields disabled:
form = PasswordForm(request.POST or None)
And now they do not get enabled, because the submit button called 'verify' from form1 is no longer present, so the code in that branch is not executed.
Let's say url is /password_reset/ - a rough outline (untested):
#login_required
#csrf_exempt
def security_question(request):
form = PasswordVerificationForm(request.POST)
if request.method == 'POST':
if form.is_valid():
token = generate_strong_token() # Implement: generate a strong token, url safe
request.session["password_reset_token"] = token
return redirect(f'/password_reset/{token}/')
else:
return render(...)
#login_required
#csrf_exempt
def change_password(request, **kwargs):
form = PasswordForm(request.POST)
token = request.session.get('password_reset_token')
if token == kwargs['token']:
if request.method == 'POST' and form.is_valid():
del request.session['password_reset_token']
# handle password change and redirect to wherever
else:
return render(...)
else:
raise SecurityError('Invalid token')
Your urls would be something like:
urlpatterns = [
re_path('password_reset/(?P<token>[0-9A-F]{32})/', change_password)
path('password_reset/', security_question)
]
Sometimes form is validating but sometimes form is not validating and shows value error
views.py
def hai(request):
if request.method == 'POST':
obj1 = hello(request.FILES, request.POST)
if obj1.is_valid():
return HttpResponse("success")
does form need to be cleaned every time submiting?
forms.py
class hello(forms.Form):
uname = forms.CharField(max_length=100)
img = forms.FileField()
template
<html>
<head></head>
<body>
<form action= {% url 'hai' %} method="POST" enctype="multipart/form-data ">
{% csrf_token %}
<div class="d-flex">
<div class="form-group mr-2">
<label for="" class="label">Pick-up date</label>
<input type="text" name="uname" class="form-control"
placeholder="Date">
</div><br>
<div class="form-group ml-2">
<label for="" class="label">Drop-off date</label>
<input type="file" name="img" class="form-control"
placeholder="Date">
</div><br>
<input type="submit" value="Book Now" class="btn btn-primary py-3 px4">
</div>
</form>
</body>
</html>
This is the error:
The problem here is that you should always return HttpResponse (or subclass), whether yourr form is valid or not; So basically you should have:
def hai(request):
if request.method == 'POST':
obj1 = hello(request.FILES, request.POST)
if obj1.is_valid():
return HttpResponse("success")
else:
return HttpResponse("error")
or you can send back the form with it's errors in the template, if you wish.
After POST method signup page always redirects to same page without printing any message or redirecting to homepage or login page but I am tracing it in every steps by printing something to check how it is working. But I can signup a new user using python shell.
Terminal is giving me only this:
[28/Nov/2019 15:36:26] "GET / HTTP/1.1" 200 2574
[28/Nov/2019 15:36:46] "POST / HTTP/1.1" 200 2574
def signup(request):
if request.user.is_authenticated:
return render(request,'/',{})
form = UserForm(request.POST or None)
if request.method == 'POST':
print("step 2")
if form.is_valid():
user = form.save(commit= False)
username= form.cleaned_data['username']
password= form.cleaned_data['password']
user.set_password(password)
user.save()
authenticate(username= username, password= password)
Profile.objects.create(
user= user,
full_name=form.cleaned_data['full_name'],
codeforces_id= form.cleaned_data['codeforces_id'],
Uva_Id = form.cleaned_data['Uva_Id'],
points = 0,
department= form.cleaned_data['department']
)
if user is not None:
if user.is_active:
login(request,user)
return redirect('/')
return render(request, 'signup.html',{'msg':'Invalid'})
else:
error = form.errors
print("error step")
return render(request, 'signup.html',{'msg':error})
else:
return render(request,'signup.html',{})
forms.py:
class UserForm(forms.ModelForm):
password = forms.CharField(widget= forms.PasswordInput)
full_name = forms.CharField(required= True)
codeforces_id = forms.CharField(required= True)
Uva_Id = forms.CharField(required= True)
department = forms.CharField(required= True)
class Meta:
model = User
fields=('username','email','password','full_name','codeforces_id','Uva_Id','department')
signup.html:
<body>
<div class="wrapper">
<div class="inner" style="width: 500px;">
{% block content %}
<form action="" method="post" style="padding-top: 40px; padding-bottom: 50px">
{% csrf_token %}
<h3 style="margin-bottom: 20px">New Account?</h3>
<div class="form-group">
<label for="username" class="control-label">Username</label>
<input type="text" class="form-control" name="username" placeholder="username">
</div>
<div class="form-group">
<label for="email" class="control-label">Email</label>
<input type="text" class="form-control" name="email" placeholder="Email">
</div>
<div class="form-group">
<label for="password" class="control-label">password</label>
<input type="password" class="form-control" name="password" placeholder="Password">
</div>
<div class="form-group">
<label for="full_name" class="control-label">fullname</label>
<input type="text" class="form-control" name="full_name" placeholder="Full Name">
</div>
<div class="form-group">
<label for="codeforces_id" class="control-label">codeforces_id</label>
<input type="text" class="form-control" name="codeforces_id" placeholder="codeforces_id">
</div>
<div class="form-group">
<label for="Uva_Id" class="control-label">Uva_Id</label>
<input type="text" class="form-control" name="Uva_Id" placeholder="uva_id">
</div>
<div class="form-group">
<label for="department" class="control-label">department</label>
<input type="text" class="form-control" name="department" placeholder="department">
</div>
<button type="submit" style="margin-top:20px">
<span>Register</span>
</button>
<p style="color: red">{{ msg }}</p>
<a style="float: right" href="/login">Already have an account</a>
</form>
{% endblock %}
</div>
</div>
</body>
Updated:
url.py
urlpatterns = [
url(r'^$',views.index,name='index'),
url(r'^login/$',views.Login,name= 'Login'),
url(r'^signup/$',views.signup,name='signup'),
url(r'^logout/$',views.Logout,name='logout'),
You havent included the url that the form should hit on POST
[...]
<form action="{% url 'name-of-the-url-that-leads-to-your-view' %}" method="post" style
[...]