I need to register a new user so wheen I seed data I get this error
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: accounts_user.username
model.py:
from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from phonenumber_field.modelfields import PhoneNumberField
# custom manager
class UserManager(BaseUserManager):
"""Define a model manager for User model with no username field."""
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""Create and save a User with the given email and password."""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
"""Create and save a regular User with the given email and password."""
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
"""Create and save a SuperUser with the given email and password."""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
GENDER_CHOICES = (
('M', "Male"),
('F', "Female"),
('O', "Other"),
)
class User(AbstractUser):
#username = None
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True
)
date_of_birth = models.DateField(default='1990-01-01')
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True)
picture = models.ImageField(
upload_to='img/users', null=True, verbose_name=""
)
phone = PhoneNumberField()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
objects = UserManager()
def save(self, **kwargs):
if not (self.is_staff or self.is_superuser):
password = self.password
if password is not None:
self.set_password(password)
super(User, self).save(**kwargs)
name = f"{self.first_name} {self.last_name}"
Profile.objects.create(
name=name, dob=self.date_of_birth, user=self)
return self
else:
return super(User, self).save(**kwargs)
def __str__(self):
return self.email
view.py
from django.shortcuts import render,redirect
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from django.conf import settings
from django.urls import reverse_lazy,reverse
from django.views.generic import CreateView
from .forms import UserRegistrationForm,UserLoginForm
User = settings.AUTH_USER_MODEL
def get_success_urls(request):
"""
Handle Success Url After Login
"""
if 'next' in request.GET and request.GET['next'] != '':
return request.GET['netx']
else:
return reverse('candidates:home')
def login(request):
form = UserLoginForm(request.POST or None)
if request.user.is_authenticated:
return redirect('/')
else:
if request.method == 'POST':
if form.is_valid():
auth.login(request, form.get_user())
return HttpResponseRedirect(get_success_urls(request))
context = {
'form': form,
}
return render(request, 'accounts/login.html',context)
def user_registration(request):
"""
Handle user registration
"""
form = UserRegistrationForm(request.POST or None)
if form.is_valid():
form = form.save()
return redirect('accounts:login.html')
context = {
'form': form,
}
return render(request, 'accounts/user-registration.html', context)
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth import authenticate
from .models import User
class UserRegistrationForm(UserCreationForm):
def __init__(self, *args, **kwargs):
UserCreationForm.__init__(self, *args, **kwargs)
self.fields['gender'].required = True
self.fields['first_name'].label = "First Name :"
self.fields['last_name'].label = "Last Name :"
self.fields['email'].label = "Email :"
self.fields['password1'].label = "Password"
self.fields['password2'].label = " Confirm Password"
self.fields['gender'].label = "Gender"
self.fields['phone'].label = "Phone"
self.fields['date_of_birth'].label = "Date Of Birth"
self.fields['first_name'].widget.attrs.update(
{
'placeholder': 'Enter First Name',
}
)
self.fields['last_name'].widget.attrs.update(
{
'placeholder': 'Enter Last Name',
}
)
self.fields['email'].widget.attrs.update(
{
'placeholder': 'Enter Email',
}
)
self.fields['password1'].widget.attrs.update(
{
'placeholder': 'Enter Password',
}
)
self.fields['password2'].widget.attrs.update(
{
'placeholder': 'Confirm Password',
}
)
self.fields['phone'].widget.attrs.update(
{
'placeholder': 'Enter Phone',
}
)
self.fields['date_of_birth'].widget.attrs.update(
{
'placeholder': 'Enter Date Of Birth',
}
)
class Meta:
model = User
fields = ['first_name', 'last_name', 'email', 'phone',
'password1', 'password2', 'gender', 'date_of_birth']
error_messages = {
"first_name": {"required": "First name is required", "max_length": "Name is too long"},
"last_name": {"required": "Last name is required", "max_length": "Last Name is too long"},
"gender": {"required": "Gender is required"},
}
def clean_gender(self):
gender = self.cleaned_data.get('gender')
if not gender:
raise forms.ValidationError("Gender is required")
return gender
def save(self, commit=True):
user = UserCreationForm.save(self, commit=False)
user.role = "user"
if commit:
user.save()
return user
class UserLoginForm(forms.Form):
email = forms.EmailField(
widget=forms.EmailInput(attrs={'placeholder': 'Email', })
)
password = forms.CharField(
strip=False, widget=forms.PasswordInput(attrs={'placeholder': 'Password', }))
def clean(self, *args, **kwargs):
email = self.cleaned_data.get("email")
password = self.cleaned_data.get('password')
if email and password:
self.user = authenticate(email=email, password=password)
try:
user = User.objects.get(email=email)
except User.DoesNotExist:
raise forms.ValidationError("User Does not exist")
if not user.check_password(password):
raise forms.ValidationError("Password is not Match")
if not user.is_active:
raise forms.ValidationError("User is not Active")
return super(UserLoginForm, self).clean(*args, **kwargs)
def get_user(self):
return self.user
What is causing such an error? I researched similar posts on this platform but each case is unique.
can any one help me?
It's what the error says. You have set up using email addresses as the username and unique = True. So you can't have 2 users with the same email address. Try using a different email address. Does the superuser use the same email as the user your are trying to sign up?
Related
I have Django with python-social-auth installed.
My custom user model:
class User(AbstractUser):
"""Custom User model."""
username = None
email = models.EmailField(blank=False, unique=True, verbose_name=_("Email"))
facebook_link = models.URLField(blank=True, verbose_name=_("Facebook profile link"))
contacts = models.CharField(blank=True, max_length=250, verbose_name=_("Contacts"))
hometown = models.CharField(blank=True, max_length=250, verbose_name=_("Hometown"))
start_coordinates = models.CharField(blank=True, max_length=100, verbose_name=_("Start coordinates"))
avatar = ProcessedImageField(
upload_to="avatar/",
format="JPEG",
options={"quality": 80},
default="avatar/default_avatar.jpg",
verbose_name=_("Image"),
)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
def __str__(self):
"""Model representation."""
return self.email
def get_absolute_url(self):
"""Get url to User's model instance."""
return reverse_lazy("public-profile", kwargs={"user_id": self.pk})
def get_full_name(self):
"""Concatenate fist and last names."""
full_name = " ".join([self.first_name, self.last_name])
return full_name.strip()
get_full_name.short_description = _("Full name")
class Meta:
verbose_name = _("User")
verbose_name_plural = _("Users")
Managers.py
class UserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def create_user(self, email, password=None, **extra_fields):
"""Create and save a User with the given email and password."""
if not email:
raise ValueError(_("Email required"))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
"""Create and save a SuperUser with the given email and password."""
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("is_active", True)
if extra_fields.get("is_staff") is not True:
raise ValueError(_("Superuser must have is_staff=True."))
if extra_fields.get("is_superuser") is not True:
raise ValueError(_("Superuser must have is_superuser=True."))
return self.create_user(email, password, **extra_fields)
I do succesfull authentication with Facebook with this code:
AUTHENTICATION_BACKENDS = (
'social_core.backends.github.GithubOAuth2',
'social_core.backends.google.GoogleOAuth2',
'social_core.backends.facebook.FacebookOAuth2',
'django.contrib.auth.backends.ModelBackend',
)
SOCIAL_AUTH_USER_MODEL = 'accounts.User'
SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True
SOCIAL_AUTH_LOGIN_REDIRECT_URL = 'home'
SOCIAL_AUTH_LOGIN_URL = 'login'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email', 'user_link', 'user_hometown']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'fields': 'id, name, email, picture.type(large), link, hometown'
}
SOCIAL_AUTH_FACEBOOK_EXTRA_DATA = [
('name', 'name'),
('email', 'email'),
('picture', 'avatar'),
('link', 'facebook_link'),
('hometown', 'hometown'),
]
As a result, I have a new user instance created in DB with the automatically populated fields:
fist_name, last_name, email.
How do I can populate the rest of fields (facebook_link, hometown) with data from response?
I am build project ,when i run python manage.py makemigrations
i got this error
File "/mnt/c/Users/ZAKARIA/Desktop/project/Accounts/admin.py", line 45, in <module>
class UpdateUserForm(forms.ModelForm):
File "/mnt/c/Users/ZAKARIA/Desktop/project/env/lib/python3.8/site-packages/django/forms/models.py", line 327, in __new__
raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (is_staff) specified for User
** Here is my code for models.py**
import datetime
from django.core.mail import send_mail
from distutils.command.upload import upload
from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.utils import timezone
from phonenumber_field.modelfields import PhoneNumberField
from .managers import UserManger
GENDER_MALE = "m"
GENDER_FEMALE = "f"
OTHER = "o"
GENDER_CHOICES = (
(GENDER_MALE, "Male"),
(GENDER_FEMALE, "Female"),
(OTHER, "Other"),
)
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True)
picture = models.ImageField(
upload_to='images/users', null=True, verbose_name="")
is_active = models.BooleanField(default=True)
#is_staff = models.BooleanField(default=False)
phone = PhoneNumberField()
is_admin = models.BooleanField(default=False)
#credits =models.PositiveIntegerField(default=100)
linkedin_token = models.TextField(blank=True, default='')
expiry_date = models.DateTimeField(null=True, blank=True)
objects = UserManger()
USERNAME_FIELD = 'email'
REQURTED_FIELDS = []
def get_full_name(self):
full_name = '%S %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
return self.first_name
def __str__(self):
return self.email
def has_perm(self, prem, obj=None):
"Does the user have a specific permission?"
return True
def has_module_perm(self, app_label):
"Does the user have permissions to view the app `app_label`?"
return True
#property
def is_staff(self):
"Is the user a member of staff"
return self.is_admin
"""#property
def is_out_of_credits(self):
"Is the user out of credits"
return self.credits > 0
#property
def has_sufficient_credits(self,cost):
return self.credits - cost >= 0
"""
#property
def linkedin_signed_in(self):
return bool(self.linkedin_token) and self.expiry_date > timezone.now()
** Here is my code for manangers.py **
from django.contrib.auth.base_user import BaseUserManager
class UserManger(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, phone, password, **extra_fields):
if not email:
raise ValueError('Users must hava an email address')
user = self.model(
email.self.normalize_email(email),
phone=phone,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, phone, email, password=None, **extra_fields):
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, phone, password, **extra_fields)
def create_superuser(self, email, phone, password, **extra_fields):
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must hava is_superuser=True.')
return self._create_user(email, phone, password, **extra_fields)
** Here is my code for admin.py**
from pyexpat import model
import django
from django.contrib import admin
from django import forms
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import User
class AddUserForm(forms.ModelForm):
"""
new User Form . Requires password confirmation.
"""
password1 = forms.CharField(
label='Password', widget=forms.PasswordInput
)
password2 = forms.CharField(
label='Confirm password', widget=forms.PasswordInput
)
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'gender')
def clean_password2(self):
# check that the two password entries match
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):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UpdateUserForm(forms.ModelForm):
"""
Update User Form ,Doesn't allow changing password in the Admin
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = (
'email', 'password', 'first_name', 'gender', 'last_name', 'is_active',
'is_staff'
)
def clean_password(self):
return self.initial["password"]
class UserAdmin(BaseUserAdmin):
form = UpdateUserForm
add_form = AddUserForm
list_display = ('email', 'first_name', 'last_name',
'gender', 'is_staff')
list_filter = ('is_staff',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {
'fields': ('first_name', 'last_name', 'gender')}),
('Permissions', {'fields': ('is_active', 'is_staff')}),
)
add_fieldsets=(
(
None,
{
'classes':('wide',),
'fields':(
'email','first_name', 'last_name', 'gender','password1','password2'
)
}
),
)
search_fields=('email','first_name','last_name')
ordering =('email','first_name','last_name')
filter_horizontal = ()
admin.site.register(User, UserAdmin)
** Here is my code for forms.py**
from django.contrib.auth import authenticate
from django.contrib.auth.forms import UserCreationForm
from Accounts.models import User
class UserRegistrationForm(UserCreationForm):
def __init__(self, *args, **kwargs):
UserCreationForm.__init__(self, *args, *kwargs)
self.fields['gender'].required = True
self.fields['first_name'].label = "First Name :"
self.fields['last_name'].label = "Last Name :"
self.fields['email'].label = "Email :"
self.fields['password1'].label = "Password"
self.fields['password2'].label = " Confirm Password"
self.fields['gender'].label = "Gender"
self.fields['phone'].label = "Phone"
self.fields['date_of_birth'].label = "Date Of Birth"
self.fields['first_name'].widget.attrs.update(
{
'placeholder': 'Enter First Name',
}
)
self.fields['last_name'].widget.attrs.update(
{
'placeholder': 'Enter Last Name',
}
)
self.fields['email'].widget.attrs.update(
{
'placeholder': 'Enter Email',
}
)
self.fields['password1'].widget.attrs.update(
{
'placeholder': 'Enter Password',
}
)
self.fields['password2'].widget.attrs.update(
{
'placeholder': 'Confirm Password',
}
)
self.fields['phone'].widget.attrs.update(
{
'placeholder': 'Enter Phone',
}
)
self.fields['date_of_birth'].widget.attrs.update(
{
'placeholder': 'Enter Date Of Birth',
}
)
class Meta:
model = User
fields = ['first_name', 'last_name', 'email', 'phone',
'password1', 'password2', 'gender', 'date_of_birth']
def clean_gender(self):
gender = self.cleaned_data.get('gender')
if not gender:
raise forms.ValidationError("Gender is required")
return gender
def save(self, commit=True):
user = UserCreationForm.save(self, commit=False)
user.role = "user"
if commit:
user.save()
return user
class UserLoginForm(forms.Form):
email = forms.EmailField(
widget=forms.EmailInput(attrs={'placeholder': 'Email', })
)
password = forms.CharField(
strip=False, widget=forms.PasswordInput(attrs={'placeholder': 'Password', }))
def clean(self, *args, **kwargs):
email = self.cleaned_data.get("email")
password = self.cleaned_data.get('password')
if email and password:
self.user = authenticate(email=email, password=password)
try:
user = User.objects.get(email=email)
except User.DoesNotExist:
raise forms.ValidationError("User Does not exist")
if not user.check_password(password):
raise forms.ValidationError("Password is not Match")
if not user.is_active:
raise forms.ValidationError("User is not Active")
return super(UserLoginForm, self).clean(**args, **kwargs)
def get_user(self):
return self.user
** Here is my code for views.py**
from django.shortcuts import render
from django.contrib import messages, auth
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect, get_list_or_404
from django.urls import reverse, reverse_lazye
from matplotlib.style import context
from Accounts.forms import *
def get_success_urls(request):
"""
Handle Success Url After Login
"""
if 'next' in request.GET and request.GET['next'] != '':
return request.GET['netx']
else:
return reverse('jobs:home')
def user_registration(request):
"""
Handle user registration
"""
form = UserRegistrationForm(request.POST or None)
if form.is_valid():
form = form.save()
return redirect('Accounts:login')
context = {
'form': form
}
return render(request, 'accounts/user-registeration.html', context)
def user_logIn(request):
"""
Provides users to logIn
"""
form = UserLoginForm(request.POST or None)
if request.user.is_authenticated:
return redirect('/')
else:
if request.method == 'POST':
if form.is_valid():
auth.login(request, form.get_user())
return HttpResponseRedirect(get_success_urls(request))
context = {
'form': form,
}
def user_logOut(request):
"""
Provide the ability to logout
"""
auth.logout(request)
messages.success(request, 'You are Successfully logged out')
return redirect('Accounts:login')
I already took out all of the is_staff attribute in admin.py and still got an error.
Refactored it many times to check if the problem is in different areas of my code.
can any one help me to solve this problem
Double check this is correct:
fields = (
'email', 'password', 'first_name', 'gender', 'last_name', 'is_active',
'is_staff'
the is_staff field, is that an actual field of your user model ?
I want to login user via email and password.
I'm unable to do that. Please Help me to fix this issue. I shall be very thankful to you.
I tried to use some authenticate stuff and try to login the user but getting multiple email value.
forms.py
class CustomLoginForm(forms.Form):
email = forms.EmailField(
max_length=254,
label='',
widget=forms.EmailInput(
attrs={'autocomplete': 'email', 'placeholder': 'Enter your email'}
)
)
password = forms.CharField(
max_length=254,
label='',
strip=False,
widget=forms.PasswordInput(
attrs={'autocomplete': 'current-password', 'placeholder': 'Password'}
)
)
error_messages = {
'invalid_login': _(
"Please enter a correct %(email)s and password. Note that both "
"fields may be case-sensitive."
),
'inactive': _("This account is inactive."),
}
def __init__(self, request=None, *args, **kwargs):
"""
The 'request' parameter is set for custom auth use by subclasses.
The form data comes in via the standard 'data' kwarg.
"""
self.request = request
self.user_cache = None
super().__init__(*args, **kwargs)
# Set the max length and label for the "username" field.
self.email = User._meta.get_field(User.EMAIL_FIELD)
email_max_length = self.email_field.max_length or 254
self.fields['email'].max_length = email_max_length
self.fields['email'].widget.attrs['maxlength'] = email_max_length
if self.fields['email'].label is None:
self.fields['email'].label = capfirst(self.email_field.verbose_name)
# class Meta:
# model = User
# fields = ['email','password']
def authenticate(self,request, email=None, password=None, **kwargs):
if email is None:
email = kwargs.get(User.EMAIL_FIELD)
if email is None or password is None:
return
try:
user = User._default_manager.get(email=email)
except User.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
User().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def user_can_authenticate(self, user):
"""
Reject users with is_active=False. Custom user models that don't have
that attribute are allowed.
"""
is_active = getattr(user, 'is_active', None)
return is_active or is_active is None
def clean(self):
email = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
if email is not None and password:
self.user_cache = self.authenticate(self.request, email=email, password=password)
if self.user_cache is None:
raise self.get_invalid_login_error()
else:
self.confirm_login_allowed(self.user_cache)
return self.cleaned_data
def confirm_login_allowed(self, user):
"""
Controls whether the given User may log in. This is a policy setting,
independent of end-user authentication. This default behavior is to
allow login by active users, and reject login by inactive users.
If the given user cannot log in, this method should raise a
``ValidationError``.
If the given user may log in, this method should return None.
"""
if not user.is_active:
raise ValidationError(
self.error_messages['inactive'],
code='inactive',
)
def get_user(self):
return self.user_cache
def get_invalid_login_error(self):
return ValidationError(
self.error_messages['invalid_login'],
code='invalid_login',
params={'email': self.email_field.verbose_name},
)
models.py
class User(auth.models.User,auth.models.PermissionsMixin):
def __str__(self):
return "#{}".format(self.username)
If more code is require then tell me in a comment section , I will update my question with that information.
Traceback
An AuthenticationForm [GitHub] is not a ModelForm, but a simple form, so adding a Meta does not make much sense: it will not construct form fields.
What you will need to do is define the (extra) form fields in your form, so:
from django import forms
from django.utils.translation import gettext, gettext_lazy as _
class CustomLoginForm(AuthenticationForm):
email = forms.EmailField(
max_length=254,
label='',
widget=forms.EmailInput(
attrs={'autocomplete': 'email', 'placeholder': 'Enter your email'}
)
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['password'].widget.attrs['placeholder'] = ('Password')
self.fields['password'].label = ''
This will however still include the username since we inherit this from the parent user. Likely it is better to construct a simple form, and look at the AuthenticationForm to implement part of the logic:
from django import forms
from django.contrib.auth import authenticate
from django.core.exceptions import ValidationError
from django.utils.translation import gettext, gettext_lazy as _
class CustomLoginForm(forms.Form):
email = forms.EmailField(
max_length=254,
label='',
widget=forms.EmailInput(
attrs={'autocomplete': 'email', 'placeholder': 'Enter your email'}
)
)
password = forms.CharField(
max_length=254,
label='',
strip=False,
widget=forms.PasswordInput(
attrs={'autocomplete': 'current-password', 'placeholder': 'Password'}
)
)
def clean(self):
email = self.cleaned_data['email']
password = self.cleaned_data['password']
user = authenticate(email=email, password=password)
if user is None:
raise ValidationError('No combination of email and password found')
self.user = user
return self.cleaned_data
In the view, we can then use the login(…) function [Django-doc]:
from django.contrib.auth import login as auth_login
def my_view(request):
if request.method == 'POST':
form = CustomLoginForm(request.POST, request.FILES)
if form.is_valid():
user = form.user
auth_login(request, user)
# …
else:
# …
# …
We should implement a backend that can work with an email address, like:
# appname/backends.py
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
UserModel = get_user_model()
class EmailBackend(ModelBackend):
def authenticate(self, request, email=None, password=None):
if email is None or email is None:
return
try:
user = UserModel._default_manager.get(email=email)
except (UserModel.DoesNotExist, UserModel.MultipleObjectsReturned):
UserModel().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
we can then set this as a backend by specifying the AUTHENTICATION_BACKENDS setting [Django-doc]:
# settings.py
# …
AUTHENTICATION_BACKENDS = [
'appname.backends.EmailBackend'
]
# …
Please help. The signup page keeps showing this field is required error. I'm a beginner. thankyouu
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class UserManager(BaseUserManager):
def create_user(self, email, username, full_name, password=None):
if not email:
raise ValueError("Users must have an email adress")
if not username:
raise ValueError("Users must have a username")
if not password:
raise ValueError("Users must have a password")
if not full_name:
raise ValueError("Users must have a name")
user = self.model(
email=self.normalize_email(email), # return lowercase
username=username,
full_name=full_name,
)
user.set_password(password) # users set password and change password
user.full_name = full_name
user.save(using=self._db)# using the default database in settings.py
return user
def create_superuser(self, email, username, full_name, password=None):
user = self.create_user(
email=self.normalize_email(email), # return lowercase
username=username,
full_name=full_name,
password=password,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db) # using the default database in settings.py
return user
class Account(AbstractBaseUser):
email = models.EmailField(
verbose_name="email",
max_length=60,
unique=True,
)
username = models.CharField(max_length=30, unique=True)
full_name = models.CharField(max_length=30, blank=True, null=True)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
profile_image = models.ImageField(max_length=255, null=True, blank=True, default=default_profile)
hide_email = models.BooleanField(default=True)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username", "full_name"]
objects = UserManager() # tie account to my custom user manager
def __str__(self):
return self.username
# "Does the user have a specific permission?"
def has_perm(self, perm, obj=None):
return True
# "Does the user have permissions to view the app `app_label`?"
def has_module_perms(self, app_label):
return True
views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login, logout, authenticate
from account.forms import RegistrationForm, AccountAuthenticationForm
def register_view(request):
user = request.user
if user.is_authenticated:
return redirect('home')
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email').lower()
raw_password = form.cleaned_data.get('password1')
user = authenticate(email=email, password=raw_password)
login(request, user)
return redirect('home')
else:
form = RegistrationForm()
return render(request, 'account/register.html', {'registration_form': form})
def login_view(request):
context = {}
user = request.user
if user.is_authenticated:
return redirect("home")
if request.POST:
form = AccountAuthenticationForm(request.POST)
if form.is_valid():
email = request.POST.get('email')
password = request.POST.get('password')
user = authenticate(request, email=email, password=password)
if user is not None:
login(request, user)
return redirect("home")
else:
form = AccountAuthenticationForm()
context['login_form'] = form
return render(request, "account/login.html", context)
def logout_view(request):
logout(request)
return redirect("home")
forms.py
from django import forms
from django.contrib.auth import get_user_model
from .models import Account
from django.contrib.auth import authenticate
User = get_user_model()
class RegistrationForm(forms.ModelForm):
full_name = forms.CharField()
email = forms.EmailField(max_length=60, help_text='Required. Add a valid email address.')
password1 = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(widget=forms.PasswordInput, label='Confirm password')
class Meta:
model = Account
fields = (
'email',
'username',
'full_name',
'password1',
'password2',
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.email = self.cleaned_data.get('email')
user.username = self.cleaned_data.get('username')
user.full_name = self.cleaned_data.get('full_name')
if commit:
user.save()
return user
def clean_email(self):
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError(f"Email {email} is already taken")
return email
def clean_username(self):
username = self.cleaned_data.get('username')
qs = User.objects.filter(username=username)
if qs.exists():
raise forms.ValidationError(f"Username {username} is already taken")
return username
def clean(self):
data = self.cleaned_data
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password2 != password1:
raise forms.ValidationError("Passwords must match")
return data
class AccountAuthenticationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
class Meta:
model = Account
fields = ('email', 'password')
def clean(self):
if self.is_valid():
email = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
if not authenticate(email=email, password=password):
raise forms.ValidationError("Incorrect username or password")
The cause of the problem could be due to the username field and email field being used one in place of the other.
An example found in the code mentioned above:
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username", "full_name"]
The problem can be resolved by verifying and fixing these errors where the email field is used in place of username field and vice versa.
Most likely there is a error in your fields html id and name so the form validation registers it as an empty value
if request.method == "POST":
updated_request = request.POST.copy()
updated_request.update({'username': request.POST['email']})
form = RegistrationForm(updated_request)
in my custom user model that is created with AbstractBaseUser when i try to add widgets which lets me add classes or place holders or input type etc.. it works only for the full_name and email fields but not for password1 and password2
in my models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.conf import settings
class MyAccountManager(BaseUserManager):
def create_user(self, email, full_name, password=None):
if not email:
raise ValueError('Users must have an email address')
if not full_name:
raise ValueError('Users must have a name')
user = self.model(
email=self.normalize_email(email),
full_name=full_name,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, full_name, password):
user = self.create_user(
email=self.normalize_email(email),
full_name=full_name,
password=password,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(verbose_name="Email",max_length=250, unique=True)
username = models.CharField(max_length=30, unique=True, null=True)
date_joined = models.DateTimeField(verbose_name='Date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='Last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
full_name = models.CharField(verbose_name="Full name", max_length=150, null=True)
profile_pic = models.ImageField(null=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['full_name']
objects = MyAccountManager()
def __str__(self):
return self.full_name
# For checking permissions.
def has_perm(self, perm, obj=None):
return self.is_admin
# For which users are able to view the app (everyone is)
def has_module_perms(self, app_label):
return True
#i also have another text model which i don't think that is needed
in my forms.py
from django.forms import ModelForm
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate
from .models import *
class TextForm(ModelForm):
class Meta:
model = Text
fields = ['title','document','requirements','deadline']
widgets = {
'title' : forms.TextInput(attrs={'placeholder':'Title','class':'form-control m-2 mb-4 pb-2'}),
'deadline' : forms.DateInput(attrs={'placeholder':'Deadline','type':'date','class':'form-control m-2 pt-2',
'id':'opendate'}),
'requirements' : forms.Textarea(attrs={'placeholder':'requirements','class':'form-control col m-2','rows':'3'}),
'document' : forms.Textarea(attrs={'placeholder':'document','class':'form-control'}),
}
class SignupForm(UserCreationForm):
class Meta:
model = User
fields = ("full_name","email","password1","password2")
widgets = {
'full_name' : forms.TextInput(attrs={'placeholder':'Full name'}),
'email' : forms.EmailInput(attrs={'placeholder':'Email'}),
'password1' : forms.PasswordInput(attrs={'placeholder':'Password'}),
'password2' : forms.PasswordInput(attrs={'placeholder':'Password2'}),
}
class SigninForm(forms.ModelForm):
class Meta:
model = User
fields = ('email','password')
widgets = {
'email' : forms.EmailInput(attrs={'placeholder':'Email','class':'form-control'}),
'password' : forms.PasswordInput(attrs={'placeholder':'Password','class':'form-control'}),
}
def clean(self):
if self.is_valid():
email = self.cleaned_data['email']
password = self.cleaned_data['password']
if not authenticate(email=email,password=password):
raise forms.ValidationError("Invalid login")
in my view.py file
def home(request):
user = request.user
# for creating posts
form = TextForm()
if request.method == "POST":
form = TextForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
author = User.objects.filter(email=user.email).first()
obj.author = author
form.save()
form = TextForm()
texts = Text.objects.all().order_by('-id')
# for signing in
if request.POST:
signin_form = SigninForm(request.POST)
if signin_form.is_valid():
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user:
login(request, user)
else:
signin_form = SigninForm()
# for signing up
signup_form = SignupForm()
if request.method == 'POST':
signup_form = SignupForm(request.POST)
if signup_form.is_valid():
User = signup_form.save()
full_name = signup_form.cleaned_data.get('full_name')
email = signup_form.cleaned_data.get('email')
raw_password = signup_form.cleaned_data.get('password1')
account = authenticate(email=email, password=raw_password)
login(request, account)
context = {'signin_form':signin_form,'signup_form':signup_form,'form': form, 'texts': texts}
return render(request, 'main/home.html', context)
NB: in the template i rendred them one by one like: {{signup_form.full_name}} , {{signup_form.password1}} etc... and it's working fine in terms of the backend