I created a custom user model because i needed the user to sign in using email instead of username. If a user signs up on the frontend, the password is hashed just fine but when i try to create a password from Django's backend, the password is saved as plain text.
admin.py
def save(self, commit=True):
# Save the provided password in hashed format
user = super(RegisterForm, self).save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
forms.py
class RegisterForm(forms.ModelForm):
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_email(self):
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def clean_password2(self):
# Check that the two password entries match
password = self.cleaned_data.get("password")
password2 = self.cleaned_data.get("password2")
if password and password2 and password != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
user = super(RegisterForm, self).save(commit=False)
user.set_password(self.cleaned_data['password'])
# user.is_applicant = True
user.is_active = True
if commit:
user.save()
return user
Please for some assistance.
Maybe you should create the user using the official function see create_user . https://docs.djangoproject.com/en/2.2/ref/contrib/auth/#django.contrib.auth.models.UserManager.create_user
Edit your def save to this in your User creation form in admin.py,
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data['password'])
if commit:
user.save()
return user
Related
I'm learning Django and tried to write my own custom user model. I'm not using DRF and serializers and stuffs I have no idea about :)
I am using createView to create users but I can't login because "Invalid password."
I checked the user's password in admin and the user's password is "Invalid password format or unknown hashing algorithm." .
here are the codes:
Custome User and User Manager in models
class UserManager(UserManager):
def create_user(self, username, email, password, **extra_fields):
if not email:
raise ValueError('User must have email')
if not username:
raise ValueError('User must have username')
user = User.objects.create_user(
username=username,
email=self.normalize_email(email),
)
user.set_password(password)
user.save()
return user
def create_superuser(self, username, email, password, **extra_fields) :
user = self.create_user(username, email, password)
user.is_staff = True
user.is_superuser = True
user.is_admin = True
user.is_active = True
user.save()
return user
class User(AbstractBaseUser):
username = models.CharField(unique=True, max_length=200)
email = models.EmailField(unique=True)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
modified_at = models.DateTimeField(auto_now=True)
objects = UserManager()
REQUIRED_FIELDS = ["username","email", "password"]
USERNAME_FIELD = "username"
def __str__(self):
return self.email
def has_perm(self, perm, object=None):
"Does the user have a specific permission?"
return self.is_admin
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
SignUp and login in views
class SignUp(CreateView):
model = User
form_class = CUForm
success_url = reverse_lazy('index')
def login(request):
if request.user.is_authenticated:
messages.warning(request, 'You are already logged in.')
return redirect('/list')
elif 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('/list')
else:
try:
user = User.objects.get(username=username)
messages.error(request, 'Invalid password.')
except:
messages.error(request, 'Invalid username ')
return redirect('login')
return render(request, 'accounts/login.html')
and forms.py
class CUForm(forms.ModelForm):
username = forms.CharField(max_length=200)
email = forms.EmailField(widget=forms.EmailInput())
password = forms.CharField(widget=forms.PasswordInput())
confirm_password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ['email','username','password',]
def clean(self):
cleaned_data = super(CUForm, self).clean()
password = cleaned_data.get('password')
confirm_password = cleaned_data.get('confirm_password')
if password != confirm_password:
raise forms.ValidationError('Password does not match.')
and admin
class CostumeUserAdmin(UserAdmin):
list_display = ('email', 'username', 'is_active', 'is_admin')
filter_horizontal = ()
list_filter = ('is_staff',)
fieldsets = ()
admin.site.register(User, CostumeUserAdmin)
I have read some of the solutions and I changed
user = self.model(
username=username,
email=self.normalize_email(email)
)
to
user = User.objects.create_user(
username=username,
email=self.normalize_email(email),
)
Alrigh I have fixed the "Invalid password format or unknown hashing algorithm." issue by adding this to my createView:
def form_valid(self, form):
user = form.save(commit=False)
password = self.request.POST['password']
user.set_password(password)
user.save()
return super().form_valid(form)
and the password now saves correctly, not sure why but it does.
And then I realized I didn't add AUTH_USER_MODEL = 'accounts.User'
in my setting.py!
I still don't know why I need to use set_password in form_valid even tho I used it in UseManager but now It works!
The problem is when i try to register this error show up:
django.db.utils.IntegrityError: NOT NULL constraint failed: accounts_user.password
I tried to migrate and did all recommended things like migrations but it didn't work.
This is my files
views.py
from django.shortcuts import render
from django.urls import reverse
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse,HttpResponseRedirect
from django.contrib.auth import authenticate,login,logout
from django.views.generic import FormView,TemplateView,ListView
from django.conf import settings
from .forms import RegisterForm
from .models import User
# Create your views here.
#user-login view
def register(request):
registred=False
if request.method=="POST":
user_register=RegisterForm(data=request.POST)
if user_register.is_valid():
username=user_register.cleaned_data.get('username')
email=user_register.cleaned_data.get('email')
password=user_register.cleaned_data.get('password1')
user=User.objects.create(username=username,email=email,password=password)
user.set_password(user.password)
user.save()
registred=True
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse('there is a problem')
else:
return render(request,'register.html',{'registred':registred,'user_register':RegisterForm})
def user_login(request):
if request.method=='POST':
email=request.POST.get('email')
password=request.POST.get('password')
user=authenticate(email=email,password=password)
if user is not None:
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse("Account not found")
else:
return render(request,'login.html')
#user-logout view
#login_required
def user_logout(request):
logout(request)
return HttpResponseRedirect(reverse('index'))
#registration view
forms.py:
# accounts.forms.py
from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import User
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email','username','full_name','short_name','password')
def clean_username(self):
username = self.cleaned_data.get('username')
if User.objects.filter(username__iexact=username).exists():
raise forms.ValidationError('This username already exists')
return username
def clean_email(self):
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
class UserAdminCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('email', 'password', 'active', 'admin')
def clean_password(self):
return self.initial["password"]
models.py
# accounts.models.py
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
# accounts.models.py
class UserManager(BaseUserManager):
def create_user(self, email, password=None):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, email, password):
"""
Creates and saves a staff user with the given email and password.
"""
user = self.create_user(
email,
password=password,
)
user.staff = True
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(
email,
password=password,
)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
# hook in the New Manager to our Model
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
username=models.CharField(default='',unique=True,max_length=50)
full_name=models.CharField(default='',max_length=50)
short_name=models.CharField(default='',max_length=50)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
# notice the absence of a "Password field", that is built in.
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [] # Email & Password are required by default.
def get_full_name(self):
# The user is identified by their email address
return self.full_name
def get_short_name(self):
# The user is identified by their email address
return self.short_name
def __str__(self): # __unicode__ on Python 2
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"Is the user a member of staff?"
return self.staff
#property
def is_admin(self):
"Is the user a admin member?"
return self.admin
#property
def is_active(self):
"Is the user active?"
return self.active
objects = UserManager()
i just changed this password=user_register.cleaned_data.get('password') to this password=request.POST.get('password') and it worked
i want to make login social auth and i use userprofile to login, but i getting error. This is error:
Exception Type: TypeError at /complete/facebook/
Exception Value: create_user() takes at least 3 arguments (2 given)
this is my admin.py code
class CustomUserCreationForm(UserCreationForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password Confirmation', widget=forms.PasswordInput)
class Meta(UserCreationForm.Meta):
model = UserProfile
fields = ('username', 'email','password')
def clean_username(self):
username = self.cleaned_data["username"]
try:
UserProfile._default_manager.get(username=username)
except UserProfile.DoesNotExist:
return username
raise forms.ValidationError(self.error_messages['duplicate_username'])
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords do not match.")
return password2
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
this is model.py
class MyUserManager(BaseUserManager):
def create_user(self, username, email, password=None):
if not email:
raise ValueError('Users must have an email address')
if not username:
raise ValueError('Users must have a username')
user = self.model(
username = username,
email = self.normalize_email(email),
)
user.is_active = True
user.set_password(password)
user.save(using=self._db)
return user
# def create_user(self, username, email):
# return self.model._default_manager._create_user(username=username)
def create_superuser(self, username, email, password):
user = self.create_user(username=username, email=email, password=password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
i already put password in fields class Meta(UserCreationForm.Meta) but its still same error.
can you help me solve this problem?
As the error mentions, create_user() expects at least three arguments but you provide only two (username and email) while defining fields. Django documentation covers this pretty well. Try adding a password field and see if it works.
I'm using Django 1.7 and am trying to authenticate a user with email instead of the provided Django auth user.
This is my models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=MyUserManager.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
user = self.create_user(email,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser):
"""
Custom user class.
"""
email = models.EmailField('email address', unique=True, db_index=True)
joined = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
def __unicode__(self):
return self.email
and this is a snippet from my views.py
def auth_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect('/')
else:
return HttpResponseRedirect('/invalid/')
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
print "Form is valid"
form.save()
return HttpResponseRedirect('/register_success/')
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
return render_to_response('register.html', args, context_instance=RequestContext(request))
and finally, my forms.py
from django import forms
from django.contrib.auth.models import User
class MyRegistrationForm(forms.ModelForm):
"""
Form for registering a new account.
"""
email = forms.EmailField(widget=forms.EmailInput,label="Email")
password1 = forms.CharField(widget=forms.PasswordInput,
label="Password")
password2 = forms.CharField(widget=forms.PasswordInput,
label="Password (again)")
class Meta:
model = User
fields = ['email', 'password1', 'password2']
def clean(self):
"""
Verifies that the values entered into the password fields match
NOTE: Errors here will appear in ``non_field_errors()`` because it applies to more than one field.
"""
cleaned_data = super(MyRegistrationForm, self).clean()
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:
if self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError("Passwords don't match. Please enter both fields again.")
return self.cleaned_data
def save(self, commit=True):
user = super(MyRegistrationForm, self).save(commit=False)
user.set_password(self.cleaned_data['password1'])
if commit:
user.save()
return user
Whenever I try to register an account, I get an error 'NoneType' object has no attribute '_insert' from forms.py calling user.save and views.py calling form.save. I don't really know how to write the user.save, but I'd imagine that would fix both errors.
Can anyone help me?
look at forms.py imports
from django.contrib.auth.models import User
must import MyUser instead of that
same in
class Meta:
model = User
fields = ['email', 'password1', 'password2']
and add to MyUser class
objects = MyUserManage()
change to
class Meta:
model = MyUser
fields = ['email', 'password1', 'password2']
and settings.py must set:
AUTH_USER_MODEL = '<apppath>.MyUser'
I want to create my own form for user createion of django.contrib.auth.models.User in Django, but I cant find a good example. Can someone help me?
you want to create a form?
create a form say forms.py
from django.contrib.auth.models import User
from django import forms
class CreateUserForm(forms.Form):
required_css_class = 'required'
username = forms.RegexField(regex=r'^[\w.#+-]+$',
max_length=30,
label="Username",
error_messages={'invalid': "This value may contain only letters, numbers and #/./+/-/_ characters."})
email = forms.EmailField(label="E-mail")
password1 = forms.CharField(widget=forms.PasswordInput,
label="Password")
password2 = forms.CharField(widget=forms.PasswordInput,
label="Password (again)")
def clean_username(self):
existing = User.objects.filter(username__iexact=self.cleaned_data['username'])
if existing.exists():
raise forms.ValidationError("A user with that username already exists.")
else:
return self.cleaned_data['username']
def clean_email(self):
#if you want unique email address. else delete this function
if User.objects.filter(email__iexact=self.cleaned_data['email']):
raise forms.ValidationError("This email address is already in use. Please supply a different email address.")
return self.cleaned_data['email']
def clean(self):
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:
if self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError("The two password fields didn't match.")
return self.cleaned_data
create a view say views.py
def create_inactive_user(request):
if request.method=='POST':
frm=CreateUserForm(request.POST)
if frm.is_valid():
username, email, password = frm.cleaned_data['username'], frm.cleaned_data['email'], frm.cleaned_data['password1']
new_user = User.objects.create_user(username, email, password)
new_user.is_active = True # if you want to set active
new_user.save()
else:
frm=CreateUserForm()
return render(request,'<templatepath>',{'form'=frm})
it is better to use django-registration