Django: Created django user that are extended with my django model field - python

Here it's my django model
class student(User):
name = models.CharField(max_length = 200)
phone_no = models.BigIntegerField()
email_id = models.EmailField()
version = models.IntegerField()
now I want to register user that are extend by my model fields.
here its my student register code
def registerStudent(request):
print request.body
if request.body:
dataDictionary = json.loads(request.body)
username = dataDictionary['username']
first_name = dataDictionary['first_name']
last_name = dataDictionary['last_name']
email = dataDictionary['email']
password = dataDictionary['password']
password1 = dataDictionary['password1']
user=User()
user.username = username
user.first_name = first_name
user.last_name = last_name
user.email = email
if password == password1:
user.set_password(password)
else:
return HttpResponse(json.dumps([{"validation": "Password does not match", "status": False}]), content_type="application/json")
user.save()
here something wrong
I want to take json as a input and create user using above model field.

I seems that you only save the user when the passwords don't match, after the return. Move the "user.save()" line one tab to the left.

The code should be:
if password == password1:
user.set_password(password)
user.save()
else:
return HttpResponse(json.dumps([{"validation": "Password does not match"
,"status": False}])
,content_type="application/json")
Now the user will be saved when password = password1, if that what you want.

Related

Django cannot authenticate or password hashing is wrong

I use a custom user model so I can authenticate using email instead of username.
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
PermissionsMixin,
)
class UserManager(BaseUserManager):
def create_user(
self,
email,
password,
confirm_code=None,
username=None,
role=None,
):
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.confirm_code = confirm_code
user.save()
return user
def create_superuser(self, email, password, role, username=None):
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.role = role
user.is_staff = True
user.is_active = True
user.is_superuser = True
user.save()
return user
class User(AbstractBaseUser, PermissionsMixin):
EM = "EM"
SM = "SM"
DH = "DH"
ST = "ST"
ROLES = [
(EM, "Executive Management"),
(SM, "Senior Management"),
(DH, "Department Head"),
(ST, "Staff Member"),
]
objects = UserManager()
role = models.CharField(max_length=2, choices=ROLES, default=US, blank=True)
username = models.CharField(max_length=20, unique=True, blank=True, null=True)
email = models.EmailField(max_length=255, unique=True)
slug = models.SlugField(blank=True, null=True)
confirm_code = models.CharField(max_length=20, null=True, blank=True)
is_active = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
has_profile = models.BooleanField(default=False)
email_verified_at = models.DateTimeField(auto_now=False, null=True, blank=True)
code = models.CharField(max_length=8, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created at")
updated_at = models.DateTimeField(auto_now=True, verbose_name="Updated at")
class Meta:
verbose_name = "User"
verbose_name_plural = "Users"
ordering = ["username"]
db_table = "users"
def get_absolute_url(self):
return f"{self.slug}"
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["role"]
When I register a user the user is created in the database correctly and the password is hashed I assume correctly, because I see the hash and not the raw password. Here is the method I used to register a user with:
#api_view(["POST"])
def RegisterUser(request, *args, **kwargs):
code = []
numbers = range(7)
for num in numbers:
code.append(randint(0, 9))
email = request.data["email"]
confirmemail = request.data["confirmemail"]
password = request.data["password"]
confirmpassword = request.data["confirmpassword"]
errors = []
if email != confirmemail:
errors.append("emailmatch")
return Response("Emails do not match", status=500)
if confirmpassword != password:
errors.append("passmatch")
return Response("Password do not match", status=500)
if User.objects.filter(email=email):
errors.append("emailexists")
return Response("User is already registered", status=500)
else:
pass
if len(errors) > 0:
return Response(False)
else:
password_to_save = make_password(password)
confirm_code = "".join(str(e) for e in code)
user = User.objects.create_user(
email=email, password=password_to_save, confirm_code=confirm_code
)
token = Token.objects.create(user=user)
from_email = "info#website.com"
link = f"http://127.0.0.1:8000/api/v1/users/confirm/{user.id}/{token}/"
context = {"link": link, "code": code}
template = get_template("emails/welcome.html").render(context)
subject = "Successfully registered"
message = "Welcome to website"
try:
send_mail(
subject,
message=message,
from_email=from_email,
recipient_list=[email],
html_message=template,
)
except:
return Response("Could not send mail")
serializer = RegisterSerializer(user)
return Response(serializer.data)
I have a custom backend to authenticate a user using an email instead of a username and here that is:
class EmailBackend(ModelBackend):
def authenticate(self, request, **kwargs):
email = kwargs.get("email", None)
user = User.objects.get(email=email)
if user:
breakpoint()
if user.check_password(kwargs.get("password", None)):
return user
else:
return None
else:
User.DoesNotExist
return None
It just doesn't work and I cannot log in. The user is active! If I do a breakpoint() as seen here and I check the password manually by entering the raw password in user.check_password('password') then it returns false. So isn't check_password supposed to then hash the raw password entered and compare that hash with the hash in the database or how does it work?
This works:
password = "hello"
saved = make_password(password)
true = check_password(password, saved)
So how why does it not work in my Authenticate backend which is exactly the same?
Do I need to use another hashing algorithm or what?
What am I supposed to do then and how can I authenticate a user? Is there another way to compare the password a user entered on a form and the hashed password saved in the database?
You are using set_password function in create_user in your manager. This method itself calls make_password function.
So, when you pass a hashed password generated via make_password to create_user, that hashed password would be hashed again in set_password function.
So there is no need to call make_password by yourself. Just pass plain password to create_user method.

get OneToOneField data from User models on firsttime save()

i want to extend my User models and add fields to it in another models
and i want it to save two of the form at once
each form works fine on its own but
the problem is that when i combine them the
i cant get the username from the User model
class Information(models.Model):
Username = models.OneToOneField(User, on_delete=models.CASCADE)
i tried this views.py
RegisterForm = self.form_class(request.POST)
InfoForm = self.second_form_class(request.POST)
if RegisterForm.is_valid() and InfoForm.is_valid():
username = request.POST.get('username')
password = request.POST.get('password')
email = request.POST.get('email')
first_name = request.POST.get('first_name')
last_name = request.POST.get('last_name')
User_obj = User(username=username, password=password, email=email, first_name=first_name,
last_name=last_name)
user = User_obj.save()
Username = username
PhoneNo = request.POST.get('PhoneNo')
Address = request.POST.get('Address')
Country = request.POST.get('Country')
Info_obj = Information(Username=Username , PhoneNo=PhoneNo, Address=Address, Country=Country)
Info_obj.save()
forms.py
class RegisterForm(forms.ModelForm):
username = forms.CharField(max_length=40)
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ["username","password", "email", "first_name", "last_name"]
class InfoForm(forms.ModelForm):
Username = forms.CharField(max_length=40, required=False)
class Meta:
model = Information
fields = ["Username","PhoneNo","Address","Country"]
did i miss something here?
it can save to the User but it doesn't save to Information model
I think the problem is with the Username on InfoForm
the problem was with the InfoForm's Username field
instead of directly getting the value from the RegisterForm
username = request.POST.get('username')
# with this code below Django demands that i need username instance from User model
Username = username
so after saving RegisterForm, i get the value from the User Database with a objects.get() method
Username = User.objects.get(username=username)
Solution
RegisterForm = self.form_class(request.POST)
InfoForm = self.second_form_class(request.POST)
if RegisterForm.is_valid() and InfoForm.is_valid():
username = request.POST.get('username')
password = request.POST.get('password')
email = request.POST.get('email')
first_name = request.POST.get('first_name')
last_name = request.POST.get('last_name')
User_obj = User(username=username, password=password, email=email, first_name=first_name,
last_name=last_name)
User_obj.save()
# i call the username from the User database after saving them
Username = User.objects.get(username=username)
PhoneNo = request.POST.get('PhoneNo')
Address = request.POST.get('Address')
Country = request.POST.get('Country')
Info_obj = Information(Username=Username , PhoneNo=PhoneNo, Address=Address, Country=Country)
Info_obj.save()
don't know if i had explained it correctly
Cheers

Django - How to authenticate a password with MD5 hash

So I'm trying to use the authentication method in my views, but always return "Does not exist", I'm using MD5 hash for my password field, so I don't know if thats the problem
forms.py
class LoginForm(forms.Form):
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput)
#This Method Hash the password
def clean_password(self):
clearPassNoHash = self.cleaned_data['password']
self.password = md5.new(clearPassNoHash).hexdigest()
return self.password
views.py
def auth_login(request):
args = {}
form = LoginForm(request.POST)
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user is not None:
login(request, user)
print("Exist")
else:
print("Does not exist")
I've tried with check_password() method(in my forms) that actually works
but I don't know why I'm having trouble with the authenticate()
-----------------------------UPDATE--------------------------------
Views.py
def auth_login(request):
args = {}
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None:
print("existe")
print user
else:
print user
args['form'] = form
return render(request, 'login/login.html', args)
forms.py
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
Other observation:
I have this in my settings.py to use my custom model
AUTH_PROFILE_MODULE = 'StudentUsers.StudentRegistration'
and this is the username field I add to my model:
class StudentRegistration(AbstractBaseUser, models.Model):
username = models.CharField(max_length = 25, null=False, default="", unique=True)
You need to get the email and password from the form's cleaned_data, not from the request directly. Read more on the cleaned_data attribute from the docs : https://docs.djangoproject.com/en/1.9/ref/forms/api/#django.forms.Form.cleaned_data
password = form.cleaned_data['password']
You should not be hashing the password value yourself. That is what authenticate already does; so in effect you are hashing twice.

Django. Best way to have unique email in User model?

I have a UserProfile model to add some things to my User model and one thing I want to do is have unique email for users so I added an email attribute to my UserProfile model and set it to unique=True like this :
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name="profile")
email = models.EmailField(unique=True)
avatar = models.ForeignKey(Avatar)
...
I created a custom form for the registration to add some infos directly to my UserProfile :
class CreateUserForm(forms.Form):
username = forms.CharField(max_length=30, label="Pseudo")
password1 = forms.CharField(widget=forms.PasswordInput, label="Password")
password2 = forms.CharField(widget=forms.PasswordInput, label="Confirmez pwd")
email = forms.EmailField(widget=forms.EmailInput, label="E-mail")
avatar = AvatarChoiceField(widget=forms.RadioSelect, queryset=Avatar.objects.all(), label="Avatar")
def clean_username(self):
username = self.cleaned_data.get('username')
if User.objects.filter(username=username).exists():
raise forms.ValidationError("This username is already used")
return username
def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 != password2:
raise forms.ValidationError("Your passwords do not match")
return password1
def clean_email(self):
email = self.cleaned_data.get('email')
if UserProfile.objects.filter(email=email).exists():
raise forms.ValidationError("This email is already used")
return email
And then in my views.py I treat my form like that :
def create_user(request):
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
username = form.clean_username()
email = form.clean_email()
password = form.clean_password2()
username = form.cleaned_data['username']
avatar = form.cleaned_data['avatar']
user = User.objects.create_user(username=username, password=password)
user.save()
user_profile = UserProfile(user=user, email=email, avatar=avatar)
user_profile.save()
else:
form = CreateUserForm()
return render(request, 'accounts/create.html', locals())
Finally I used the email of the form for my UserProfile model and not for my User model. And by this way I have a unique email for my users. And it's working.
Am I doing it right or is there a better way to achieve what I want ?
You are on the right track, the only thing that doesn't look right is that you shouldn't call clean method manually like this:
# These are not needed in your view method
username = form.clean_username()
email = form.clean_email()
password = form.clean_password2()
They are already called by form.is_valid(). See this SO question for details.

Custom authentication not logging in user with correct password

I have a user in my database with the login jim#test.com and password jimrox. I'm trying to log him in with this view:
def login(request):
email = request.POST.get("email", "")
password = request.POST.get("password", "")
user = authenticate(username=email, password=password)
My custom authentication looks partly like this:
class login(object):
def authenticate(self, username=None, password=None):
# auth user based on email
try:
user = Freelancer.objects.get(email=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
When the user attempts to check_password() it doesn't return the user even though the password is correct. Am I meant to create my own check_password() function in the model?
Here is my model also:
class FreelancerManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
class Freelancer(AbstractBaseUser):
email = models.EmailField()
first_name = models.CharField(max_length=128, primary_key=True)
surname = models.CharField(max_length=128)
university = models.CharField(max_length=256)
verified = models.BooleanField(default=False)
created_date = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email'
If I am meant to create my own password check, how would I do that? This is with 1.8 also.
EDIT
Here is how I add my users to the database:
views.py
def freelancer_signup(request):
if request.method == 'POST':
form = FreelancerForm(request.POST)
if form.is_valid():
freelancer = form.save(commit=False)
freelancer.save()
return render(request, 'freelancestudent/index.html')
else:
return render(request, 'freelancestudent/index.html')
else:
form = FreelancerForm()
return render(request, 'freelancestudent/freelancersignup.html', {'form': form})
forms.py
from django import forms
from models import Freelancer
class FreelancerForm(forms.ModelForm):
class Meta:
model = Freelancer
password = forms.CharField(widget=forms.PasswordInput)
fields = ('email', 'first_name', 'surname', 'university', 'password')

Categories