Django not accepting valid credentials - django

views.py. My default user login template, I have tried both methods listed below and don't know where I am makeing a mistake - I get an error that my credentials are incorrect every time
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db() # load the profile instance created by the signal
user.profile.university = form.cleaned_data.get('university')
user.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
#user_login(request, user)
return redirect('main:main_page')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
def user_login(request):
'''
Using different method for getting username, tried this and didn't work either
if request.method == 'POST':
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request,user)
messages.info(request, "Successfully signed in")
return redirect('main:home')
else:
message = 'Sorry, the username or password you entered is not valid please try again.'
return render(request, 'login.html', {'message':message})
else:
message = 'Invalid'
return render(request, 'login.html', {'message':message})
else:
form=AuthenticationForm()
return render(request, 'login.html', {"form":form})
'''
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request,user)
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse("Your account was inactive.")
else:
message = 'Sorry, the username or password you entered is not valid please try again.'
return render(request, 'login.html', {'message':message})
else:
message = 'Request failed please try again.'
return render(request, 'login.html', {'message':message})
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=100, blank=True)
last_name = models.CharField(max_length=100, blank=True)
email = models.EmailField(max_length=150)
bio = models.TextField()
university = models.CharField(max_length=30)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def update_profile_signal(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
forms.py
class SignUpForm(UserCreationForm):
university = forms.CharField(max_length=30)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email','university', 'password1', 'password2',)
app urls.py
app_name = 'main'
urlpatterns=[
path('signup/',views.signup,name='signup'),
path('user_login/',views.user_login,name='user_login'),
path('main_page/',views.main_page,name='main_page'),
]
login.html form
<form method="POST" action="{% url 'main:user_login' %}/" class="form-signin">
{%csrf_token%}
<div class="form-label-group">
<input type="text" name="username" id="inputText" class="form-control" placeholder="Username" required autofocus>
<br/>
</div>
<div class="form-label-group">
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
</div>
<div class="custom-control custom-checkbox mb-3">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<label class="custom-control-label" for="customCheck1">Remember password</label>
</div>
<input type="submit" class="form-control" name="" value="Login">
<hr class="my-4">
<p>Don't have account? Sign up here</p>
{% if message %}<p style="color: red;">{{message}}</p>{% endif %}
Forgot Password
</form>
I cannot figure out why my Django does not accept correct credentials. Which part of my code seems to be incorrect?

make sure to define the right user model to django settings, add
# AUTH_USER_MODEL = 'YOUR_APP_NAME.YOUR_CUSTOM_USER_MODEL'
to your django settings .like # AUTH_USER_MODEL = 'users.User'
and you need to write an abstract user model .
from django.contrib.auth.models import AbstractUser
class RightsSupport(models.Model):
class Meta:
managed = False # No database table creation or deletion \
# operations will be performed for this model.
permissions = (
("add_user", "Can Create User"),
("view_user", "Can View Single User"),
("change_user", "Can Change User"),
("list_user", "Can View User List"),
("add_plan", "Can Create Plan"),
("view_plan", "Can View Single Plan"),
("change_plan", "Can Change Plan"),
("list_plan", "Can View Plan List"),
)
class User(AbstractUser):
CREATED = 0
ACTIVE = 1
BANNED = 2
KICKED = 3
UPGRADE = 4
STS = (
(CREATED, 'Just Created'),
(ACTIVE, 'Activated'),
(BANNED, 'Disabled'),
(KICKED, 'Disabled'),
(UPGRADE, 'Active'),
)
status = models.IntegerField(choices=STS, default=CREATED, blank=True, null=True)
def __str__(self):
return self.username
also update your view, that code has a huge mistake on it . you forget to close docstring .
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db() # load the profile instance created by the signal
user.profile.university = form.cleaned_data.get('university')
user.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
#user_login(request, user)
return redirect('main:main_page')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
def user_login(request):
'''
Using different method for getting username, tried this and didnt work either
'''
if request.method == 'POST':
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request,user)
messages.info(request, "Successfully signed in")
return redirect('main:home')
else:
message = 'Sorry, the username or password you entered is not valid please try again.'
return render(request, 'login.html', {'message':message})
else:
message = 'Invalid'
return render(request, 'login.html', {'message':message})
else:
form=AuthenticationForm()
return render(request, 'login.html', {"form":form})

Related

Django forms: Update a user's attributes without changing username

I'm trying to create a form that allows a user to update their username or avatar. The problem that I am running into is that if I update the profile picture without changing the username, the django form validation if form.is_valid() will recognize the form as invalid, since the username already exists in the database. I'm using an update view, though I'm not sure I've implemented it correctly.
When I try to update the avatar without changing the username, I get a page that says "Form is invalid" from the line: HttpResponse("Form is invalid"). Is there a workaround to remove the form validation? I have tried removing if form.is_valid(): but received the error 'User_form' object has no attribute 'cleaned_data'.
I feel like there has to be an easy way around this that I have not been able to find, as so many sites allow you to update only one attribute at a time.
Views.py
model = User
form = User_form
fields = ['username', 'avatar']
template_name_suffix = '_update_form'
def update_profile(request, user_id):
if request.method == "POST":
form = User_form(request.POST, request.FILES)
if form.is_valid():
user = User.objects.get(pk=user_id)
username = form.cleaned_data['username']
avatar = form.cleaned_data['avatar']
if username != user.username:
user.username = username
if avatar != user.avatar:
if avatar:
user.avatar = avatar
user.save()
return redirect('index')
else:
return HttpResponse("Form is invalid")
models.py
class User(AbstractUser):
followed_by = models.ManyToManyField("User", blank=True, related_name="following")
avatar = models.ImageField(upload_to='profilepics/', verbose_name='Avatar', null=True, blank=True)
class User_form(ModelForm):
class Meta:
model = User
fields = ['username', 'avatar']
user_update_form.html
<form action="/profile/{{user.id}}/update" method="post" enctype='multipart/form-data'>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update">
</form>
You are doing too much work yourself. Django's ModelForms can not only create data, but update data as well. You pass the instance through the instance=… parameter:
from django.shortcuts import get_object_or_404
def update_profile(request, user_id):
user = get_object_or_404(User, pk=user_id)
if request.method == 'POST':
form = User_form(request.POST, request.FILES, instance=user)
if form.is_valid():
form.save()
return redirect('index')
else:
return HttpResponse('Form is invalid')
else:
form = User_form(instance=user)
return render(request, 'some_template.html', {'form': form})
For uniqness checks, it will exclude the instance when checking if the username already exists. So one can change the username, given the new username of course does not yet exists.

Django 3.0: Unable to get username in template

I have issue is that in template, I automatically get access of username of Superuser (if that is logged-in) but not username of user based on Buyer (Model). User is getting registered and also can login (I can see it in database). But in template I am unable to get username of user other than superuser. I don't what i am missing here. So i am putting all code of view.py here. Also after user logging he sees bookrepo:home and i am using user logic in header.html (bookrepo:home extends header.html)
I have model named Buyer in models.py file. And based on this model, two modelForm has made.
This is code of model.py
class Buyer(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.OneToOneField(User, on_delete=models.DO_NOTHING)
# additional attributes
contact = models.CharField('Contact #', max_length=16, unique=True, validators=[
RegexValidator(
regex=r'^\+?1?\d{9,15}$',
message="Phone number (Up to 15 digits) must be entered in the format: '+923001234567'."
),
], )
devices = models.CharField('Devices', unique=False, max_length=115, blank=True)
picture = models.ImageField(upload_to=profile_pic_path, null=True,blank=True)
def __str__(self):
return "{} {}".format(self.user.first_name, self.user.last_name)
class Meta:
get_latest_by = '-user.date_joined'
This is code of modelForms
class RegistrationForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
confirm_password = forms.CharField(widget=forms.PasswordInput())
class Meta():
model = User
fields = ('username',
'email',
'password')
def clean(self):
cleaned_data = super(RegistrationForm, self).clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password != confirm_password:
raise forms.ValidationError(
"Password and Confirm Password does not match"
)
class RegistrationFormPlus(forms.ModelForm):
class Meta():
model = Buyer
fields = ('contact',)
This is code of header.html (NOT the home.html)
{% if user.is_authenticated %}
<a class="nav-link" href="{% url 'bookrepo:logout' %}">Logout</a>
<h2>Welcome {{ user.username }}!</h2>
{% else %}
<a class="nav-link" href="{% url 'bookrepo:user_login' %}">Login</a>
{% endif %}
This is code of views.py
def home(req):
bookz = Book.objects.order_by('title')
var = {'books': bookz, 'range': 10}
return render(req, 'bookrepo/home.html', context=var)
def registration(request):
registered = False
if request.method == 'POST':
reg_form = RegistrationForm(data=request.POST)
reg_form_plus = RegistrationFormPlus(data=request.POST)
if reg_form.is_valid() and reg_form_plus.is_valid():
user = reg_form.save()
user.set_password(user.password)
user.save()
user_plus = reg_form_plus.save(commit=False)
user_plus.user = user
user_plus.save()
registered = True
else:
print(reg_form.errors, reg_form_plus.errors)
print("else 2 chala")
else:
reg_form = RegistrationForm()
reg_form_plus = RegistrationFormPlus()
return render(request, 'bookrepo/signup.html',
{'reg_form': reg_form,
'reg_form_plus': reg_form_plus,
'registered': registered
})
#login_required
def special(request):
return HttpResponse("You are logged in. Nice!")
#login_required
def user_logout(request):
logout(request)
return HttpResponseRedirect(reverse('bookrepo:home'))
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user:
return HttpResponseRedirect(reverse('bookrepo:home'))
else:
print("Someone tried to login and failed.")
print("They used username: {} and password: {}".format(username, password))
return HttpResponse("Invalid login details supplied.")
else:
return render(request, 'bookrepo/login.html', {})
You should use {{ buyer.user.username }} in your template to show the username of a user.
You are trying to extend your django user framework with a One To One Field . new extended Django Model used to store the extra information that relates to the User Model. {{user.username}} gives the username from session.
use this code to authenticate users don't forgot to import
from django.contrib.auth.models import User,auth
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('index')
else:
messages.info(request,'invalid user')
return redirect('login')
else:
return render(request,"login.html")

why im unable to authenticate other users except the super user in django?

I have used the default path('',include("django.contrib.auth.urls")) in django to perform login,password reset operations for my project,I have thoroughly checked my signup form and the database,everything goes well with the registration part,but I am unable to authenticate all other users except the super user,what might be the reason for this issue?
myproject/urls.py:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('home/', include('home.urls')),
path('accounts/',include('accounts.urls')),
path('',include("django.contrib.auth.urls"))
]
and in templates in registration directory my login form will look like
{% extends 'base.html' %}
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}
my signup view is:
class UserFormView(View):
form_class = RegForm
template_name = 'signup.html'
def get(self, request):
form = self.form_class()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = self.form_class(request.POST)
if (form.is_valid()):
form.save()
return redirect('login')
return render(request, self.template_name, {'form': form})
And then then my form:
class RegForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
confirm_password=forms.CharField(widget=forms.PasswordInput())
class Meta:
model= User
fields=['first_name','last_name','username','email','date_joined','password','confirm_password']
def clean_password(self):
password=self.cleaned_data.get("password")
confirm_password = self.cleaned_data.get("confirm_password")
if(len(password)<8):
raise forms.ValidationError("The length of the password should be minimum 8 characters")
return password
def clean_email(self):
email=self.cleaned_data.get('email')
if(validate_email(email)==False):
raise forms.ValidationError("The Email Format is In Correct")
return email
def clean_confirm_password(self):
password = self.cleaned_data.get("password")
confirm_password = self.cleaned_data.get("confirm_password")
if (password != confirm_password):
raise forms.ValidationError('Password doesn\'t match')
As I said in comments you need to save the user like this:
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False)
password = form.cleaned_data['password']
user.set_password(password)
user.save()
return redirect('login')
return render(request, self.template_name, {'form': form})
Django expects the password field of the User model to contained a hashed password. Your form stores the password in plaintext (which is a big security no-go).
I suggest you have a look at the source code of django.contrib.auth.forms.UserCreationForm on how to properly create a user.
Edit: my guess is that you can sign in with the superuser because you created it with the createsuperuser command.
This is because you incorrectly save the password. In django it perform a hashing over the password. You either use the django User password field( ref link https://docs.djangoproject.com/en/2.1/ref/contrib/auth/#django.contrib.auth.models.User.password) so your RegForm looks like
class RegForm(forms.ModelForm):
confirm_password=forms.CharField(widget=forms.PasswordInput())
class Meta:
model= User
fields=['first_name','last_name','username','email','date_joined','password','confirm_password']
def clean_password(self):
password=self.cleaned_data.get("password")
confirm_password = self.cleaned_data.get("confirm_password")
if(len(password)<8):
raise forms.ValidationError("The length of the password should be minimum 8 characters")
return password
def clean_email(self):
email=self.cleaned_data.get('email')
if(validate_email(email)==False):
raise forms.ValidationError("The Email Format is In Correct")
return email
def clean_confirm_password(self):
password = self.cleaned_data.get("password")
confirm_password = self.cleaned_data.get("confirm_password")
if (password != confirm_password):
raise forms.ValidationError('Password doesn\'t match')
Or
save the hashed value of input passwor in the post method. So the code look like
def post(self, request):
form = self.form_class(request.POST)
if (form.is_valid()):
user_form = form.save(commit=False)
user_form.set_password(request.POST.get('password'))
user_form.save()
return redirect('login')
return render(request, self.template_name, {'form': form})

Django - Template displays edited user context info despite ValidationError

Hi I'm working on a form to edit a user's profile. It properly updates the fields upon successful submission without any validation errors. The problem I'm having is that if the form does return a validation error upon submission and I've changed the name on the form, the template will display this new name instead of the old name. I'm assuming this is because it uses the user context provided by the POST request. Is there any way to properly display the user's old name until the form is actually successfully submitted? Below is my code.
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.forms import ModelForm
class UserProfileForm(UserCreationForm):
first_name = forms.CharField(label="First Name", required=True)
last_name = forms.CharField(label="Last Name", required=True)
email = forms.EmailField(label="Email", required=True)
class Meta:
model = User
fields = ("first_name", "last_name", "email", "username", "password1", "password2")
def clean_email(self):
email = self.cleaned_data.get('email')
if email:
if User.objects.filter(email=email).exists():
raise forms.ValidationError('This email is already in use.')
return email
def save(self, commit=True):
user = super(UserProfileForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
class EditProfileForm(ModelForm):
first_name = forms.CharField(label="First Name", required=True)
last_name = forms.CharField(label="Last Name", required=True)
email = forms.EmailField(label="Email", required=True)
password1 = forms.CharField(label="New Password", widget=forms.PasswordInput)
password2 = forms.CharField(label="Repeat New Password", widget=forms.PasswordInput)
class Meta:
model = User
fields = ("first_name", "last_name", "email", "username", "password1", "password2")
def clean_email(self):
email = self.cleaned_data.get('email')
if email:
if User.objects.filter(email=email).exists():
raise forms.ValidationError('This email is already in use.')
return email
def save(self, commit=True):
user = super(EditProfileForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py
def register(request):
if request.method == 'POST':
form = UserProfileForm(request.POST)
if form.is_valid():
form.save()
new_user = authenticate(username=form.cleaned_data['username'],
password=form.cleaned_data['password1'])
login(request, new_user)
return redirect('/overview')
else:
if request.user.is_authenticated():
return redirect('/overview')
else:
form = UserProfileForm()
return render(request, "/register.html", {'form': form})
#login_required
def edit_profile(request):
if request.method == 'POST':
print request.POST
form = EditProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('/profile')
else:
form = EditProfileForm()
return render(request, '/edit_profile.html', {'form': form})
navbar.html
<li class="">
<a href="javascript:;" class="user-profile dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<img src="/ui/assets/images/user.png" alt="">{{ user.first_name }} {{ user.last_name }}
<span class=" fa fa-angle-down"></span>
</a>
<ul class="dropdown-menu dropdown-usermenu pull-right">
<li> Profile</li>
<li><i class="fa fa-sign-out pull-right"></i> Log Out</li>
</ul>
</li>
Fetch a separate instance of the user from the db to use with the form. This way, the request.user will not be modified when the form is validated.
user = User.objects.get(id=request.user.id)
form = EditProfileForm(request.POST, instance=user)

Django auth_user_model

I'd like to make auth_user_model login but I need to login with Email and Password. So I thought I can do that if I can save email value in 'username' field.
class HeepooUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=15, null=True)
allow_phone = models.BooleanField(default=False)
school = models.ForeignKey(School)
date_join = models.DateTimeField(auto_now_add=True)
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(request.POST)
profile_form = RegisterForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save(commit=False)
user.set_password(user.password)
user = user_form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile = profile_form.save()
registered = True
return HttpResponseRedirect("/books/")
else:
return HttpResponse('Wrong access1')
else:
user_form = UserForm()
profile_form = RegisterForm()
return render(request, "register.html", {
'user_form': user_form,
'profile_form': profile_form,
'registered': registered,
})
forms.py
class UserForm(forms.ModelForm):
email = forms.EmailField(max_length=50, required=True,
widget=forms.TextInput(attrs={'class':'form-control', }),
)
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('email', 'password',)
class RegisterForm(forms.ModelForm):
class Meta:
model = HeepooUser
exclude = ('allow_phone', 'user',)
Register.html
<form action="" method="post">
{% csrf_token %}
{{ user_form.as_p }}
{{ profile_form.as_p }}
<input type="submit" value="Register">
</form>
Could you please help me on?
Thanks!
You can request the email instead of username to the user in your login form in order to use it for loggin him, then just generate a username for that user, you can do it using his email or name.
EDIT:
You only need to generate an username. Let's say that you are requesting name and last name to the user. Let's create a method to generate it.
def generate_username(first_name, last_name):
username = '%s.%s' % (first_name.lower(), last_name.lower())
username = '{:.29}'.format(username)
counter = User.objects.filter(first_name=first_name,last_name=last_name).count()
if counter > 0:
username += '%s' % (counter + 1)
return username
Then you can use it on your view.
user = user_form.save(commit=False)
user.set_password(user.password)
user.username = generate_username(first_name, last_name)
.....
If you don't want to request first name or last name, you can generate the username using his email too.