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
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.
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
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.
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.
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')