Django form errors not showing when use id_<field-name> - python

I'm a beginner in Django, I try to use for="id_<field-name>" method to create a signup form interface, but the default validation like "This field is required." or "This username already exists" is not showing. I don't want to use {{ form.as_p }} because I want to separate the field. The registration still working if i input the true the valid things.
HTML
<form method="POST" class="register-form" id="register-form" enctype="multipart/form-data" >
{% csrf_token %}
<div class="form-group">
<label for="id_username"><i class="zmdi zmdi-account material-icons-name"></i></label>
<input type="text" name="username" id="username" placeholder="Username"/>
</div>
<div class="form-group">
<label for="id_email"><i class="zmdi zmdi-email"></i></label>
<input type="email" name="email" id="email" placeholder="Your Email" />
</div>
<div class="form-group">
<label for="id_password"><i class="zmdi zmdi-lock"></i></label>
<input type="password" name="password" id="password" placeholder="Password"/>
</div>
<div class="form-group">
<input type="checkbox" name="agree-term" id="agree-term" class="agree-term" />
<label for="agree-term" class="label-agree-term"><span><span></span></span>I agree all statements in Terms of service</label>
</div>
<div class="form-group form-button">
<input type="submit" name="signup" id="signup" class="form-submit" value="Register"/>
</div>
</form>
views.py
def register(request):
registered = False
if request.method == 'POST':
# Get info from "both" forms
# It appears as one form to the user on the .html page
user_form = UserForm(data=request.POST)
profile_form = UserProfileInfoForm(data=request.POST)
# Check to see both forms are valid
if user_form.is_valid() and profile_form.is_valid():
# Save User Form to Database
user = user_form.save()
# Hash the password
user.set_password(user.password)
# Update with Hashed password
user.save()
# Now we deal with the extra info!
# Can't commit yet because we still need to manipulate
profile = profile_form.save(commit=False)
# Set One to One relationship between
# UserForm and UserProfileInfoForm
profile.user = user
# Check if they provided a profile picture
if 'profile_pic' in request.FILES:
print('found it')
# If yes, then grab it from the POST form reply
profile.profile_pic = request.FILES['profile_pic']
# Now save model
profile.save()
# Registration Successful!
registered = True
else:
# One of the forms was invalid if this else gets called.
print(user_form.errors,profile_form.errors)
else:
# Was not an HTTP post so we just render the forms as blank.
user_form = UserForm()
profile_form = UserProfileInfoForm()
# This is the render and context dictionary to feed
# back to the registration.html file page.
return render(request,'basic_app/registration.html',
{'user_form':user_form,
'profile_form':profile_form,
'registered':registered,
})
forms.py
from django import forms
from django.contrib.auth.models import User
from .models import UserProfileInfo, TeaProfileInfo
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta():
model = User
fields = ('username','email','password')
My signup page interface

A quick way to validate your form by adding the following to your form.py
def clean(self):
super(UserForm, self).clean()
username = self.cleaned_data.get('username')
email = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
if username == "" or email == "" or password == "":
raise forms.ValidationError(['This field is required.'])
In your HTML make sure to add the following after/before each field
{{ username.errors }}
{{ email.errors }}
{{ password.errors }}

Related

Django 2.1.4 Registration Form + Login Page

Hi I am new to Django and need help with registration form and login. I am able to register and able to see the user credentials registered under admin register model. However, i tried to take the user-credentials in the database and then want to do a login, but unable to do so. Can someone help please.
models.py
class register(models.Model):
name = models.CharField(max_length=250)
username = models.CharField(max_length=20)
password = models.CharField(max_length=20)
occupation = models.CharField(max_length=100)
def __unicode__(self):
return str(self.username)
Views.py
#register
def registerForm(request):
if request.method == 'POST':
if request.POST.get('name') and request.POST.get('username') and request.POST.get('password') and request.POST.get('occupation'):
reg = register()
reg.name = request.POST['name']
reg.username = request.POST['username']
reg.password = request.POST['password']
reg.occupation = request.POST['occupation']
reg.save()
return render(request, 'login.html')
else:
return render(request, 'register.html')
#Login
def Login(request):
if request.method == 'POST':
if request.POST.get('username') and request.POST.get('password'):
usr_login = register()
usr_login.username = request.POST['username']
usr_login.password = request.POST['password']
usr_login.user = authenticate(username=username, password=password)
if usr_login.user:
login(request, usr_login.user)
return HttpResponseRedirect('/forum/')
else:
error = "Username and Password are invalid. Please try again."
return render(request, 'login.html')
else:
return render(request, 'login.html')
login.html
<form method="post" action="/forum/">
{% csrf_token %}
<div class="form-group">
<label for="username">Username:</label>
<input type="username" class="form-control" id="username" placeholder="Enter username" required="required">
</div>
<div class="form-group">
<label for="pwd">Password:</label>
<input type="password" class="form-control" id="pwd" placeholder="Enter password" required="required">
</div>
<div class="row">
<div class="col" align="center">
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox"> Remember me
</label>
</div>
<button type="submit" class="btn btn-primary" value="login">Submit</button><br><br>
Not yet registered? Register Here.
</form>
urls.py
# login
url(r'^login/$', views.Login, name='login'),
# register
url(r'^registeration/$', views.registerForm, name='registeration'),
You are trying to authenticate the user using the django builtin authentication backend but you are not using the django User model. In your case you have to create custom authentication logic. I strongly suggest you to hash the user's password.
If you want to use the builtin auth framework you check out the documentation for more information https://docs.djangoproject.com/en/2.1/ref/contrib/auth/

how to access Django form fields through HTML

I have created models.py, forms.py, views.py & registeration.html.
At the moment in registeration.html I am directly importing the django form like {{reg_form.as_p}}, I can also do it in following two ways: {{ form.as_table }} or {{ form.as_ul }}. what I want is to have a real control over the fields to be displayed. Meaning to say some fields may be tabular, some may be list etc with specific css.
What I tried in html to access the field is mentioned below:
id={{form.id_FullName}} name={{form.FullName}}
In models.py I have:
FullName = models.CharField(max_length = 100)
The above way didnt work, I want some way to access the django fields in HTML.
Add name and pass the modelname ,
Change like this,
<input type="text" id="id_FullName" value="" name="FullName" />.
and submit your form.
Example , lets say signup form :
forms.py,
class SignUpForm(forms.ModelForm):
email = forms.CharField(label='email', max_length=100)
password = forms.CharField(label='password', max_length=100)
def __init__(self, *args, **kargs):
super(SignUpForm, self).__init__(*args, **kargs)
class Meta:
model = User
fields = '__all__'
views.py,
def signup(request):
form = SignUpForm(request.POST or None)
if request.method == 'POST':
form = SignUpForm(request.POST or None)
if not form.is_valid():
print form.errors
return render(request, 'signup.html', {'form': form})
else:
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
new_user = User.objects.create_user(email=email,
password=password,
)
new_user.is_active = True
new_user.save()
return redirect('login')
else:
return render(request, 'signup.html', {'form': form})
urls.py
url(r'^signup', views.signup, name='signup'),
Finally in your templates ie signup.html,
<form action="." method="post"> {% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" name="email" id="inputUsernameEmail" placeholder="Email">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" id="inputPassword" placeholder="Password">
</div>
<input type="submit" name="Sign up" value="Sign up" id="Sign_up" class="button_drop outline">
</form>
You can render the field manually.[Documentation]
Here is a sample taken from the docs for a subject field
<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject }}
</div>

Django save user profile manually

I have created a Profile and attached to user model using OneToOneField. I have a registration form where user enters input which corresponds to user and profile. Django provides User.objects.create_user to save fields which are related to User model, but i don't know how to save details of Profile model manually.
Here is my code:
models.py
from django.db import models
from django.contrib.auth.models import User
def Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
full_name = models.CharField(max_length=150, required=True)
# lot more fields here
views.py
#csrf_protect
def register(request):
if request.method == 'POST':
full_name = request.POST.get('full_name', '')
username = request.POST.get('username', '')
password = request.POST.get('password', '')
User.objects.create_user(username=username, password=password)
# how to save Profile full_name here
return render(request, 'register.html')
register.html
<form method="post" action="/register/">{% csrf_token %}
<div class="form-group">
<label for="full_name">Name</label>
<input type="text" name="full_name" id="full_name">
</div>
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" value="" id="username">
</div>
<div class="form">
<label for="password">Password</label>
<input type="pass" name="password" value="" id="password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
1) How can i save full_name of Profile model in views.py ? Can I do this without creating form class for every model in the future that want to save or Signals?
2) Do I need to change auth_user_model in settings.py in order to save profile details manually?
3) How to validate the fields without creating a new Form class?
#csrf_protect
def register(request):
if request.method == 'POST':
full_name = request.POST.get('full_name', '')
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = User.objects.create_user(username=username, password=password)
Profile.objects.create(user=user,full_name=full_name)
# how to save Profile full_name here
return render(request, 'register.html')
you can use the created user instance to create the profile associated with that user

Django: invalid form

I am new to Django and is currently trying to make a user registration form for my application. Does anyone know why form.is_valid() is returning False?
forms.py
class RegistrationForm(forms.ModelForm):
username = forms.CharField(widget=forms.TextInput)
password = forms.CharField(widget=forms.PasswordInput)
email = forms.CharField(widget=forms.EmailInput)
class Meta:
model = User
fields = ['username', 'password', 'email']
views.py
def registration(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
print "valid"
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
User.objects.create_user(username=username, email=email, password=password)
user = authenticate(username=username, passsword=password)
if user is not None:
login(request, user)
return redirect('/admin')
else:
# return a blank form
print "invalid"
return render(request, 'registration/register.html', {'form': form})
register.html
<div class="container ">
<form method="post" action=".">
{% csrf_token %}
<h2 class="form-signin-heading">Register</h2>
<input type="text" id="inputUsername" class="form-control" placeholder="Username" required autofocus>
<input type="password" id="inputPassword" class="form-control" placeholder="Password" required>
<input type="email" id="inputEmail" class="form-control" placeholder="Email" required autofocus>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
I see that you defined the form in the view, but you are not using it inside the template (register.html). I would have done something more like this:
<div class="container">
<h2 class="form-signin-heading">Register</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign Up</button>
</form>
</div>
Also, if you haven't noticed, your "return render(...)" line is within the else block. And while not necessary, I think it's good practice to define context as a dict and pass it in using context=context in the view or whatever you name it. However, for the case you have here, I'd suggest using a class-based view. It's much cleaner for signing a user up.
from django.views.generic import CreateView
from django.urls import reverse_lazy
class Registration(CreateView):
form_class = RegistrationForm
template_name = 'register.html'
success_url = reverse_lazy('login')
# in the urls.py, set name='login' for the login page
# signing a user up will not grant admin priveleges, that is only done through the
# creation of a super user or if you coded your model to do so (not recommended)
and as for any validation, look into creating a clean(self) method inside the forms.py Like this:
# this will be on the same block as class Meta you defined
# ensures no other user has the username with a different case
def clean(self):
cleaned_data = super(RegistrationForm, self).clean()
username = cleaned_data.get('username')
email = cleaned_data.get('email')
# checks if username is provided and ensures the username is not already in use
if username and User.objects.filter(username__iexact=username).exists():
self.add_error('username', 'A user with that username already exists.')
# checks if email is provided and ensures this email is not already in use
if email and User.objects.filter(email__iexact=email).exists():
self.add_error('email', 'That email address is already in use.')
return cleaned_data
I saw that you were setting some labels in your template, this can be done within the forms.py on the same block as the class Meta and def clean(self) I just provided:
# method to overwrite the form label names
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Username'
self.fields['email'].label = 'Email Address'
I have not tested this, I'm going off of memory but I think this is a route similar to your use case, and it's utilizing the Django resources available to you :) Good Luck and I hope this helps!
P.S: You should look into django-crispy-forms since you're using bootstrap.
You haven't given any of your HTML input elements a name attribute. Without that, the browser can't send any data to the server.
Note that if you had used Django itself to produce the fields, they would not only include the name, but would also be populated when the invalid form was redisplayed.

Django not authenticating using custom User model

I am trying to authenticate users against an existing database. I can authenticate the user with their email and password combination but I cannot save the authorisation, meaning the user is not actually logged in.
I know this because in Template.html, it is not showing the correct options after login when I call {% if user and not user.is_anonymous %}
I believe the fault is coming from this line in views.py
auth_login(request, user)
Views.py
from django.contrib.auth import logout as auth_logout
from django.contrib.auth import login as auth_login
from django.contrib.auth import authenticate
...
def login_email(request):
if request.method == 'POST':
email = request.POST.get('email')
password = hashlib.md5(request.POST.get('password')).hexdigest()
#db query to check if email and password combination exist
user = Users.objects.get(email=email,password=password)
if user is not None:
user.backend = 'django.contrib.auth.backends.ModelBackend'
auth_login(request, user)
return redirect('/personalised')
else: #failed to return to login page
return render(request, 'login.html',{})
#invalid POST request recieved
else:
return render(request,"login.html",{})
login.html
<form action="/login_email/" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="email">Email address</label>
<input type="email" name="email" class="form-control" id="email" placeholder="Email">
</div>
<div class="form-group">
<label for="email">Password</label>
<input type="password" name="password" class="form-control" id="password" placeholder="Password">
</div>
<button type="submit" class="btn btn-info">Submit</button>
</form>
Models.py
class Users(models.Model):
visitorid = models.CharField(db_column='visitorID', max_length=80) # Field name made lowercase.
name = models.CharField(max_length=255)
source = models.CharField(max_length=4)
visits = models.IntegerField()
last_visit = models.CharField(max_length=10)
email = models.CharField(max_length=255)
unsubscribe = models.CharField(max_length=1)
twitter = models.CharField(max_length=100)
password = models.TextField()
.....
template.py
{% if user and not user.is_anonymous %}
<li>My Feed </li>
<li>Trending</li>
<li>Your Saves</li>
<li>Logout </li>
{% else %}
<button type="button" class="btn btn-success navbar-btn">Sign in with Email</button>
{% endif %}
Do not use this code:
email = request.POST.get('email')
password = hashlib.md5(request.POST.get('password')).hexdigest()
#db query to check if email and password combination exist
user = Users.objects.get(email=email,password=password)
Instead use the authenticate method. It returns a User
user = authenticate(email=email, password=password)
This assumes that you have an appropriate auth backend setup.

Categories

Resources