i created a custom form from the Django-allauth package adding a first name, Lastname and is_staff. This was after i had extended the user model using abstart user. i think it has something to do with is_staff being a boolean value. All suggestions are welcome. thank you.
My user model looks like this
from django.contrib.auth.models import AbstractUser, UserManager
class CustomUserManager(UserManager):
def get_by_natural_key(self, username):
case_insensitive_username_field = '{}__iexact'.format(self.model.USERNAME_FIELD)
return self.get(**{case_insensitive_username_field: username})
class User(AbstractUser):
is_student = models.BooleanField('student status', default=False)
location = models.CharField(max_length=30, blank=True)
# first_name= models.CharField( blank=False, max_length=30, verbose_name='first name')
email = models.EmailField(unique=True)
objects = CustomUserManager()
My custom form is as shown below
from django.contrib.auth.models import User, Group
class CustomSignupForm(SignupForm):
first_name = forms.CharField(max_length=30, label='First Name')
last_name = forms.CharField(max_length=30, label='Last Name')
is_staff = forms.BooleanField(required=True ,label = 'Are you been assigned as a staff?')
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
return user
Update your signup method and add the following line before save,
user.is_staff = self.cleaned_data['is_staff']
Related
I'm making a login for my app, with a custom user model and form, using an e-mail as username field in the model, and asking for email and password during the login process. The problem is that no matches are found in the authenticate method in my view, so I can't log in my users. Here is the code:
user model
class usuarios(AbstractBaseUser):
nombre = models.CharField(max_length=32, null=False)
apellido = models.CharField(max_length=32, null=False)
correo = models.EmailField(null=False, unique=True)
password = models.CharField(max_length=200, null=False)
fecha_nacimiento = models.DateField(null=False)
USERNAME_FIELD = 'correo'
objects = userManager()
def __str__(self):
return self.correo+' '+self.nombre+' '+self.apellido
login form
class loginForm(forms.Form):
correo = forms.EmailField()
password = forms.CharField(
widget=forms.PasswordInput()
)
class Meta:
model = usuarios
fields = ("correo","password")
login view
class usuario_login(FormView):
template_name = "user/usuario_login.html"
form_class = loginForm
success_url = reverse_lazy('user:crear')
def form_valid(self, form):
usuario = authenticate(
username=form.cleaned_data['correo'],
password=form.cleaned_data['password']
)
if usuario is not None:
login(self.request, usuario)
else:
return HttpResponseRedirect(
reverse_lazy('user:login')
)
return super(usuario_login, self).form_valid(form)
As you can see, in the login view I try to authenticate username (that's the email) and password before doing the login. I appreciate any help and then you.
Nevermind, the problem was that as I changed the AbstractBaseUser, I had to change the authentication user model too, so I just added this in settings as the documentation states:
AUTH_USER_MODEL = 'user.usuarios'
I have created 3 custom user models. However only one user under the models Users() is able to login in into a sells dashboard that I have created. I want the two user namelly, Buyer() and Supplier() to be able to login to the dashboard but not to the admin area. The following is my code. Please help me see the error.
# models.py
# These are my three custom models
from django.db import models
from django.contrib.auth.models import AbstractUser, AbstractBaseUser, UserManager, BaseUserManager, PermissionsMixin
from django.conf import settings
# Superuser model
class Users(AbstractUser):
username = models.CharField(max_length=25, unique=True)
email = models.EmailField(unique=True, null="True")
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
# Returns username
def __str__(self):
return self.username
# Supplier user model
class Supplier(AbstractBaseUser):
sname = models.CharField(max_length=255, verbose_name='Supplier Name', unique=True)
phone_number = models.CharField(max_length=255, verbose_name='Phone Number')
email_address = models.CharField(max_length=255, verbose_name='Email Address', null=True)
physical_address = models.CharField(max_length=255, verbose_name='Physical Address')
description = models.TextField(max_length=255, verbose_name='Describe yourself')
is_active = models.BooleanField(default=True)
objects = Users()
USERNAME_FIELD = 'sname'
def __str__(self):
return self.sname
# This model save inventory of a supplier
class Inventory(models.Model):
pname = models.CharField(max_length=255, verbose_name='Product Name')
quantity = models.PositiveIntegerField(verbose_name='Quantity (kgs)')
measurement = models.CharField(max_length=255, verbose_name='Measurement')
orginal_price = models.PositiveIntegerField(verbose_name='Original Price')
commission = models.PositiveIntegerField(verbose_name='Commission')
selling_price = models.PositiveIntegerField(verbose_name='Selling Price (MWK)')
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE, verbose_name='Supplier')
def __str__(self):
return self.pname
# This model saves the transaction a buyer has made
class Transaction(models.Model):
cust_name = models.CharField(max_length=255, verbose_name='Customer Name')
pid = models.ForeignKey(Inventory, on_delete=models.CASCADE, verbose_name='Product')
quantity_r = models.PositiveIntegerField(verbose_name='Quantity (KGS)')
success = models.BooleanField(default=False)
uid = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='User Id')
# Calculates actual price
def actual_price(self):
return int(self.quantity_r) * int(self.pid.selling_price)
# Returns customer name
def __str__(self):
return self.cust_name
# Calculates total costs of suppliers products
class SupplierProductCostView(models.Model):
id = models.PositiveIntegerField(primary_key=True)
sname = models.CharField(max_length=255)
price = models.PositiveIntegerField()
class Meta:
db_table = 'home_supplierproductcostview'
managed = False
def __str__(self):
return str(self.id) + ' ' + self.sname + ' ' + str(self.price)
# Buyer user model
class Buyer(AbstractBaseUser):
username = models.CharField(max_length=255, unique=True)
company_name = models.CharField(max_length=255, verbose_name='Company Name')
phone_number = models.CharField(max_length=255, verbose_name='Phone Number')
email_address = models.CharField(max_length=255, verbose_name='Email Address')
address = models.CharField(max_length=500, verbose_name='Physical Address')
description = models.TextField(max_length=255, verbose_name='Describe your company')
is_active = models.BooleanField(default=True)
objects = Users()
USERNAME_FIELD = 'username'
# Returns username
def __str__(self):
return self.username
# forms.py
# This is my registration and login form
from django import forms
from .models import Supplier, Buyer
# Custom supplier registration form
class SupplierRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat password', widget=forms.PasswordInput)
# Supplier registration form fields
class Meta:
model = Supplier
fields = ('sname', 'phone_number', 'email_address', 'physical_address', 'description')
# Password check
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords don\'t match.')
return cd['password2']
# Custom buyer registration form
class BuyerRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat password', widget=forms.PasswordInput)
# Buyer registration form fields
class Meta:
model = Buyer
fields = ('username', 'company_name', 'phone_number', 'email_address', 'address', 'description')
# Password check
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords don\'t match.')
return cd['password2']
# Login form
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
#views.py
# These are my login and logout views
from django.shortcuts import render, redirect, reverse
from django.contrib.auth import authenticate, login, logout
from users.forms import LoginForm
# User logs in to dashboard
def index(request):
if request.method == 'POST':
loginform = LoginForm(request.POST)
# Check if form is valid
if loginform.is_valid():
username = loginform.cleaned_data['username']
password = loginform.cleaned_data['password']
user = authenticate(username=username, password = password)
# If user does not exist
if user is not None:
login(request, user)
return redirect(reverse('home'))
else:
context = {
'form':loginform,
'error': 'Could not login, Please try again...',
}
return render(request, 'users/index.html', context)
loginform = LoginForm()
context = {
'form' : loginform,
}
# Returns login form
return render(request, 'users/index.html', context)
# Logout
def logout_user(request):
logout(request)
return redirect(reverse('login'))
I extended the custom user model with a OneToOneField but now I Am getting this error "django.db.utils.IntegrityError: null value in column "users_id" violates not-null constraint" apparently there is something wrong with my registration view. Can you help?
# Buyer registration view
def buyer_form_register(request):
if request.method == 'POST':
buyer_form = BuyerRegistrationForm(request.POST)
if buyer_form.is_valid():
# Create a new user object but avoid saving it yet
new_user = buyer_form.save(commit=False)
# Set the chosen password
new_user.set_password(
buyer_form.cleaned_data['password'])
# Save the User object
new_user.save()
# Create the user profile
return render(request, 'register/register_done.html')
else:
buyer_form = BuyerRegistrationForm()
return render(request, 'register/register_buyer.html', {'buyer_form': buyer_form})
# Edited model
class Buyer(AbstractBaseUser):
# New field
users = models.OneToOneField(Users, on_delete=models.CASCADE)
username = models.CharField(max_length=255, unique=True)
company_name = models.CharField(max_length=255, verbose_name='Company Name')
phone_number = models.CharField(max_length=255, verbose_name='Phone Number')
email_address = models.CharField(max_length=255, verbose_name='Email Address')
address = models.CharField(max_length=500, verbose_name='Physical Address')
description = models.TextField(max_length=255, verbose_name='Describe your company')
objects = Users()
USERNAME_FIELD = 'username'
def __str__(self):
return self.username
You can't have 3 custom user models, in settings.py you can only set AUTH_USER_MODEL to one model.
Extend your user model with profiles (OneToOneField) instead to differentiate between the different user types.
I have 2 accounts, Instructor & Student which both extend a CustomUser model. Instructors have an email field. Students have an instructor key that they select from a drop-down menu.
I am able to populate the ModelChoiceField with instructor's emails, no problem. However, I am now unable to save the selected instructor's email into the foreign key appropriately. I think the error lies in how I save the instructor_id, specifically this line,
student.instructor_id = Instructor.objects.get(email=self.cleaned_data["instructor_id"])
, but I'm not sure what the problem is. Please help!
forms.py
class StudentSignUpForm(UserCreationForm):
instructor_id = forms.ModelChoiceField(queryset=Instructor.objects.all())
class Meta(UserCreationForm):
model = CustomUser
fields = ('username', 'inGameName', 'instructor_id')
help_texts = {
'username': 'Required',
'inGameName': 'Required; A name by which you can be identified',
'instructor_id': 'Optional; Provided by your professor',
}
#transaction.atomic
def save(self):
user = super().save(commit=False)
user.is_student = True
student = Student.objects.create(user=user)
student.instructor_id = Instructor.objects.get(email=self.cleaned_data["instructor_id"])
student.save()
user.save()
return user
class InstructorSignUpForm(UserCreationForm):
email = forms.EmailField(label='Your Email', help_text='Required')
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = ('username', 'inGameName', 'email')
help_texts = {
'username': 'Required',
'inGameName': 'Required; A name by which you can be identified',
}
#transaction.atomic
def save(self):
user = super().save(commit=False)
user.is_instructor = True
instructor = Instructor.objects.create(user=user)
instructor.email = self.cleaned_data["email"]
instructor.save()
user.save()
return user
models.py
from django.contrib.auth.models import AbstractUser, UserManager as AbstractUserManager
from django.db import models
class UserManager(AbstractUserManager):
pass
class CustomUser(AbstractUser):
objects = UserManager()
is_student = models.BooleanField(default=False)
is_instructor = models.BooleanField(default=False)
username = models.CharField(max_length=40, primary_key=True, default='')
inGameName = models.CharField("In-Game Name", max_length=40, default='')
USERNAME_FIELD = 'username'
class Instructor(models.Model):
user = models.OneToOneField(CustomUser, default='USER', on_delete=models.CASCADE)
email = models.EmailField(max_length=254, unique=True, default='')
def __str__(self):
return self.email
class Student(models.Model):
user = models.OneToOneField(CustomUser, default='USER', on_delete=models.CASCADE)
instructor_id = models.ForeignKey(Instructor, to_field='email', on_delete=models.CASCADE, default='')
I just started a new Django project and I wanted to create my own customer user model instead of using the default. I pretty much followed the one in the documentation for 2.1 (my version of Django) except I added more fields and date_of_birth is called 'dob' and isn't required. But then when I create the superuser account, I can't log into the admin panel. It says, "Please enter the correct email address and password for a staff account. Note that both fields may be case-sensitive."
Here is my code:
users/models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.utils.translation import gettext_lazy as _
# Create your models here.
class UserManager(BaseUserManager):
# python manage.py createuser
def create_user(self, email: str, password: str=None) -> 'User':
if not email:
raise ValueError('Users must have a valid email address.')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
# python manage.py createsuperuser
def create_superuser(self, email, password) -> 'User':
user = self.create_user(
email=email,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(
_('email address'), help_text=_('An email address'), max_length=127, unique=True, null=False, blank=False
)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
first_name = models.CharField(_('first name'), help_text=_('The user\'s given name'), blank=False, max_length=32)
last_name = models.CharField(
_('last name'), help_text=_('The user\'s surname or family name'), blank=False, max_length=32
)
dob = models.DateField(_('date of birth'), help_text=_('User\'s date of birth'), blank=False, null=True)
hometown = models.CharField(_('hometown'), help_text=_('Hometown'), blank=True, max_length=64)
country = models.CharField(_('country'), help_text=_('Country'), blank=True, max_length=64)
objects = UserManager()
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def get_full_name(self):
return self.first_name + " " + self.last_name
def get_short_name(self):
return self.first_name
def has_perm(self, perm, obj=None):
return self.is_staff
def has_module_perms(self, app_label):
return self.is_staff
#property
def is_staff(self) -> bool:
"""
Is the user a member of staff?
:return: If the user is an admin, then True. Else False
"""
return self.is_admin
I also changed my settings.py file to read:
AUTH_USER_MODEL = 'users.User'
and I made sure the app ('myproject.users.apps.UsersConfig') is added to the INSTALLED_APPS list. Note: my apps are all located one folder in, unlike the tutorial default. Ie:
myproject/
|-----> users/
|----->models.py
I think you missed one thing in User model,
Change is_active = models.BooleanField(default=False) to is_active = models.BooleanField(default=True)
Hence your model be like,
class User(AbstractBaseUser):
is_active = models.BooleanField(default=True)
# other fields
From the official doc,
is_active
Boolean. Designates whether this user account should be considered
active. We recommend that you set this flag to False instead of
deleting accounts; that way, if your applications have any foreign
keys to users, the foreign keys won’t break.
I'm new to Django, and I've been fighting with this form for over a week now. I started this first because it is the core of my project. What I ultimately want is a single form that has a condition that the user can set, to add data to a second form when they check a radio box (will do that in jquery). I want to give admins the ability to register users, but I have a special subclass of users called operators that need additional information in a separate model. I almost have it working right now, but all users get added to the special subclass. Please help!
EDIT: What's not working is that I want to have the Admins register a user on a single form that can create users and if they check a button, then fill out the rest of the form for operators. I have the second part working (they can create an operator), but I also want them be able to create a regular user with the same form (that doesn't use the operator model). Can this be done?
Here is my code. NOTE: I messed up the password registration in this code, but I'll fix that later. Just working on this core functionality right now.
Models
class UserProfile(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
birth_date = models.DateField(null=True, blank=True)
profile_pic = models.ImageField(null=True, blank=True)
notes = models.TextField(null=True, blank=True)
def __str__(self):
return self.first_name + ' ' + self.last_name
class OperatorProfile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
cdl = models.ManyToManyField('CDL', blank=True)
endorsement = models.ManyToManyField('Endorsement', blank=True)
cdl_expiration = models.DateField(blank=True, null=True)
def __str__(self):
return str(self.user)
Views
class OperatorCreateView(CreateView):
model = OperatorProfile
template_name = 'pages/operatorprofile_form.html'
form_class = UserCreationMultiForm
success_url = reverse_lazy('index')
def form_valid(self, form):
# Save the user first, because the profile needs a user before it
# can be saved.
user = form['user'].save()
user.groups.add(Group.objects.get(name='Operators'))
profile = form['profile'].save(commit=False)
profile.user = user
profile.save()
form['profile'].save_m2m()
return redirect(reverse_lazy('index'))
Forms
# Operator Creation Form
class OperatorProfileForm(forms.ModelForm):
class Meta:
model = OperatorProfile
exclude = ['user']
class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
last_name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
username = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control'}))
password_confirm = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control'}))
email = forms.CharField(widget=forms.EmailInput(attrs={'class': 'form-control'}))
bio = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control'}))
def clean_password2(self):
password = self.cleaned_data.get('password1')
password_confirm = self.cleaned_data.get('password2')
if not password_confirm:
raise forms.ValidationError("You must confirm your password")
if password != password_confirm:
raise forms.ValidationError("Your passwords do not match")
return password_confirm
class Meta:
model = UserProfile
fields = ['username', 'password', 'password_confirm', 'first_name', 'last_name', 'bio']
class UserCreationMultiForm(MultiModelForm):
form_classes = {
'user': UserProfileForm,
'profile': OperatorProfileForm,
}