When a new user signs up for an account, the admin panel shows that a password has not been set for the user (despite saving it via views.py). Another strange thing I noticed is that the password is being saved to the email field in the database. The code appears fine. Not sure where I went wrong. Any help would be greatly appreciated.
sign up html template
{% if user.is_authenticated %}
<h2>currently logged in as {{ user.username }} </h2>
{% else %}
<h1 class="h5 text-center">Create Account</h1>
<h4>{{ error }}</h4>
<form method="POST">
{% csrf_token %}
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" autocomplete="username" placeholder="Username" id="id_username" required>
</div>
<div class="form-group">
<label for="password1">Password</label>
<input type="password" class="form-control" name="password1" placeholder="Password" autocomplete="new-password" required id="id_password1">
<small>Password must be at least 8 characters</small>
</div>
<div class="form-group">
<label for="password2">Confirm Password</label>
<input type="password" class="form-control" name="password2" placeholder="Confirm Password" autocomplete="new-password" required id="id_password2">
</div>
<ul>
<li>Your password can’t be too similar to your other personal information.</li>
<li>Your password must contain at least 8 characters.</li>
<li>Your password can’t be a commonly used password.</li>
<li>Your password can’t be entirely numeric.</li>
</ul>
<!-- <div class="form-group">
<div class="custom-control custom-checkbox text-small">
<input type="checkbox" class="custom-control-input" id="sign-up-agree">
<label class="custom-control-label" for="sign-up-agree">I agree to the <a target="_blank" href="utility-legal-terms.html">Terms & Conditions</a>
</label>
</div>
</div> -->
<button class="btn btn-primary btn-block" type="submit">Create Account</button>
</form>
views.py
def signup(request):
if request.method == 'GET':
return render(request, 'events/signup.html', {'form': UserCreationForm()})
else:
# Create new user and profile
if request.POST['password1'] == request.POST['password2']:
try:
print(request.POST['password1'])
print(request.POST['password2'])
user = User.objects.create_user(request.POST['username'], request.POST['password1'])
user.save()
login(request, user)
return redirect('home')
except IntegrityError:
return render(request, 'events/signup.html', {'form': UserCreationForm(), 'error':'Username has already been taken. Please use a different name.'})
else:
# Tell the user the passwords don't match
return render(request, 'events/signup.html', {'form': UserCreationForm(), 'error':'Passwords did not match'})
There's no mention of "email" anywhere in the code but for some reason the password gets saved as email and the actual password isn't getting set.
You need to set password explicitly, or send it in the third param, second param of create_user method is email, thats why password is being set as email.
reference to set_password method
reference to create_user method
You need something like this.
user = User.objects.create_user(username=request.POST['username'])
user.set_password('new password')
user.save()
Your code:
user = User.objects.create_user(request.POST['username'], request.POST['password1'])
user.save()
See the the docs:
create_user(username, email=None, password=None, **extra_fields)
So, oops, you send the password as second argument and it is interpreted as being the email address.
create_user(username=request.POST['username'], password=request.POST['password1'])
Should work.
Related
I have created a new table using models.py and this table stores data to my models.py table which I created.
Now when I am going to my login page its not able to authenticate the details from that table and always gives invalid credentials.
My app name which I created is User and the table name which is stored in SQLite is User_register
Login.html
<div class="wrapper gradient">
<div class="container">
<div class="row centered-form">
<div class="col-xs-12 col-sm-8 col-md-4 col-sm-offset-2 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><center><b>Login To Web App!!</b></center> </h3>
</div>
<div class="panel-body">
<form role="form" method="POST">
{% csrf_token %}
<div class="form-group">
<input type="text" name="email" id="email" class="form-control input-sm" placeholder="Username">
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-sm" placeholder="Password">
</div>
<div class="form-group">
{% for message in messages %}
<p style="color:black;">{{message}}</p>
{% endfor %}
</div>
<input type="submit" value="Login" class="btn btn-info btn-block">
</form>
</div>
</div>
</div>
</div>
</div>
</div>
Models.py
class Register(models.Model):
first_name = models.CharField(max_length=90)
last_name = models.CharField(max_length=90)
email = models.EmailField(max_length=90)
password = models.CharField(max_length=90)
Views.py
def login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
user = auth.authenticate(email=email, password=password)
if user is not None:
auth.login(request, user)
return render(request,'index.html')
else:
messages.info(request, 'Invalid credentials')
return render(request,'login.html')
else:
return render(request, 'login.html')
I may be out of touch, but
the fields youre using are premade in the standard auth backend which you easily set to use those fields. A good tutorial for this is apart of this youtube series https://youtube.com/playlist?list=PLzMcBGfZo4-kQkZp-j9PNyKq7Yw5VYjq9
Or check out a extended example with password reset etc in the register app of this repo https://github.com/HarryLudemann/Job-Search
If you still require making your own custom model i suggest you using a 'custom authbackend' this is nearly always the way togo unless you use the prebuild form check it ou here https://docs.djangoproject.com/en/3.2/topics/auth/customizing/
If You still want to use the setuo youre using you should be using the built in forms, this allows you to use the cleaned_data method check out the docs https://docs.djangoproject.com/en/3.2/ref/forms/fields/
Or look for a example in the github repo above.
If this does not answer help please post any more code, errors or info you have. Also ensure you have run the makemigrations and migrate aswell as mugrate your server setup. Hope this somewhat helps 👍
raise ValueError('The given username must be set') using django python
...
I have been trying to register a user using from django.contrib.auth.models import user
Views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth.models import User
# Create your views here.
def register(request):
if request.method == 'POST':
username = request.POST.get('username')
email = request.POST.get('email')
password1 = request.POST.get('password1')
password2 = request.POST.get('password2')
if password1 == password2:
if User.objects.filter(username = username).exists():
return redirect('register')
elif User.objects.filter(email = email).exists():
return redirect('register')
else:
user=User.objects.create_user(username = username,password =password1, email = email)
user.save()
return redirect('login')
else:
return redirect('/')
else:
return render(request, 'register.html')
def login(request):
return render(request, 'login.html')
register.html
<form method="POST" action="{% url 'register' %}">
{% csrf_token %}
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" id="username">
</div>
<div class="form-group">
<label for="password1">Password</label>
<input type="password" class="form-control" id="password1">
</div>
<div class="form-group">
<label for="password2">AGAIN Password</label>
<input type="password" class="form-control" id="password2">
</div>
<div class="form-group">
<label for="email">Email address</label>
<input type="email" class="form-control" id="email" placeholder="name#example.com">
</div>
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="check">
<label class="form-check-label" for="check">Check me out</label>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
user=User.objects.create_superuser(username = username,password =password1, email = email)
I want to know that why it is just sending that The given username is must be set but instead I have set super_user already. How to resolve this? It is not getting the username by POST method or is there any other mistake which I am ignoring?
add name attribute in your input tags, something like this:
...
<input type="text" class="form-control" id="username" name="username">
...
<input type="password" class="form-control" id="password1" name="password1">
...
<input type="password" class="form-control" id="password2" name="password2">
...
<input type="email" class="form-control" id="email" name="email" placeholder="name#example.com">
...
I think your problem here is the use of request.POST. If this is a form, you probably want to change this to be request.form wherever you're using request.POST. At the moment, your line request.POST.get("username") is returning None, so when you try to save the user it complains.
The Authentication system might be a little bit tricky if this is your first time doing it. I am going to link you with this project that i did a while ago; it has an authentication system with Django; it can help you out :
https://github.com/Nouamanezh909/BLog_repo.
--Go to Accounts, there you will find (
forms , view , everything you need.
)
I have a very common problem - after login I want to redirect to the page where login was called. I can describe situation exactly like here: Django: Redirect to previous page after login
There are 2 options where you can log in - from the home page (which is defined in base.html) and from bokeh.html (other views inherit from bokeh)
my base.html and bokeh.html have the same block to redirect to login. Difference is, that login called from home page should return to home page and from other page should return to page where was called.
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">Login</a>
</li>
my login.html
<form method="POST">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" placeholder="Enter Username" name="username" required>
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="Enter Password" name="password" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-dark">Login</button>
</div>
</form>
and views.py
def login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username,password=password)
if user is not None:
auth.login(request,user)
return redirect('home')
else:
messages.info(request,'Invalid credentials')
return redirect('login')
else:
return render(request,'login.html')
I was trying to add next to my form in login.html but it didn't work. While accessing to login from page other than home page it was like: localhost:8000/login?next=/bokeh/ and after submiting form I was still on login but URL changed to localhost:8000/login?next=. I know it's pretty hard to explain but I will add another information in need.
First, change the template to include the urlencoded next parameter to the login url:
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}?next={{ request.path |urlencode }}">Login</a>
</li>
Second, your login template needs to preserve the value of next:
<form method="POST">
<input type="hidden" name="next" value=""{{ next }}">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" placeholder="Enter Username" name="username" required>
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="Enter Password" name="password" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-dark">Login</button>
</div>
</form>
Third, your login view should retrieve the URL parameter and pass it to the template:
from django.conf import settings
def login(request):
if request.method == 'GET':
next = request.GET.get('next', settings.LOGIN_REDIRECT_URL)
return render(request, 'login.html', {'next': next})
if request.method == 'POST':
next = request.POST['next']
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username,password=password)
if user is not None:
auth.login(request,user)
return redirect(next)
else:
messages.info(request,'Invalid credentials')
return redirect('login')
Finally, you should consider using the Django Authentication Views instead of writing your own login views!
I am doing some app with Flask and I am working on registration now. I am working with SQL and not SQLAlchemy on this case (just to work with SQL a bit more)
Also using Flask-WTF for forms.
I successfully create database table:
class RegisterForm(Form):
name = StringField(
'Username',
validators=[DataRequired(), Length(min=4, max=25)]
)
email = StringField(
'Email',
validators=[DataRequired(), Length(min=6, max=40)]
)
password = PasswordField(
'Password',
validators=[DataRequired(), Length(min=6, max=40)])
confirm = PasswordField(
'Repeat Password',
validators=[DataRequired(), EqualTo('password', message='Passwords must match')]
)
In my views.py I have next for registration:
#app.route("/register/", methods=["GET", "POST"])
def register():
form = RegisterForm(request.form)
if request.method == "POST" and form.validate_on_submit():
name = request.form["name"]
email = request.form["email"]
password = request.form["password"]
g.db.connect_db()
g.db.execute("INSERT INTO users(name, email, password) VALUES (?,?,?)", (name, email, password))
g.db.commit()
g.db.close()
return render_template("register.html", form=form)
And my simple form:
<form action="/" method="post">
{{ form.csrf_token }}
<div class="form-group">
<label for="usernameInput">Username</label>
<input type="text" name="name" class="form-control" id="usernameInput">
</div>
<div class="form-group">
<label for="emailInput">Email</label>
<input type="email" name="email" class="form-control" id="emailInput">
</div>
<div class="form-group">
<label for="passwordInput">Password</label>
<input type="password" name="password" class="form-control" id="passwordInput">
</div>
<div class="form-group">
<label for="confirmInput">Confirm password</label>
<input type="password" name="confirm" class="form-control" id="confirmInput">
</div>
<button type="submit" class="btn btn-default btn-block">Register</button>
{% if error %}
<p class="error"><strong>Error:</strong> {{error}} </p>
{% endif %}
</form>
Now I have been trying, changing and fixing for 2 days and can't find a problem. When I enter all the data and click Register I get 400 Bad request.
Perhaps it something silly and I just can't see it.
If anyone can help, I would appriciate.
If need more info or code, let me know.
Thanks
Your form is posting to /, not /register/.
You haven't shown the route you defined for /, but presumably it does not accept POSTs.
I am trying to create a page to register users but the submit button in my bootstrap form isn't working. When I hit the submit button, I get a bad request error. Here is the code in my python file:
#app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
if not request.form['username']:
error = 'You have to enter a username'
elif not request.form['email'] or '#' not in request.form['email']:
error = 'You have to enter a valid email address'
elif not request.form['password']:
error = 'You have to enter a password'
elif get_user_id(request.form['username']) is not None:
error = 'The username is already taken'
else:
print(request.form['username'])
db = get_db()
db.execute('INSERT INTO user (username, email, pw_hash) VALUES (?, ?, ?)',
[request.form['username'], request.form['email'],
generate_password_hash(request.form['password'])])
db.commit()
flash('You were successfully registered and can login now')
return render_template('control.html')
return render_template('register.html')
also i have a html file register.html:
{% extends 'layout.html' %}
{% block title %}Sign-up{% endblock title %}
{% block body %}
<div class="container">
<form class="form-register" role="form" method="post" action="{{ url_for('register') }}">
<h2 class="form-register-heading">Please sign up</h2>
<label for="username" class="sr-only">Username</label>
<input type="username" id="inputUsername" class="form-control" value="{{ request.form.username }}" placeholder="Username" required autofocus>
<label for="email" class="sr-only">Email address</label>
<input type="email" id="inputEmail" class="form-control" value="{{ request.form.email }}" placeholder="Email address" required autofocus>
<label for="password" class="sr-only">Password</label>
<input type="password" id="inputPassword" class="form-control" placeholder="Password" required >
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign up</button>
</form>
</div>
{% endblock body %}
I can't find where I did it wrong, I'm new to python and flask!
Your input fields have no name attribute. This will cause all of your checks to result in KeyErrors. The first step is to add the attribute to each input.
<input name="username" type="text" id="inputUsername" class="form-control" value="{{ request.form.username }}" placeholder="Username" required autofocus>
Note that I also checked the type attribute as there is no username type. email and password are valid values, email being added in HTML5.
The next step will be to change how you check for the fields. If you only care about the presence of the field, in is the way to go.
if 'username' not in request.form:
If, however, you also want a truty value, the get method is what you want.
if not request.form.get('username'):