I have been trying to get my Django custom backend to work and it refuses to accept my credentials, which are correct in the database (I have verified this). It just keeps saying email and password are incorrect.
I am lost and don't know where to go from here with this. I really need help at this point.
VIEWS.PY
class MyLogin(LoginView):
template_name = 'employees/login.html'
success_url = 'employees:emp-home'
authentication_form = LoginForm
def get_success_url(self):
return super().get_success_url()
def form_valid(self, form):
user = self.request.POST['username']
password = self.request.POST['password']
authenticate(EmpBackend, self.request, user, password)
return HttpResponseRedirect(self.get_success_url())
MODELS.PY
class EmpUserManager(BaseUserManager):
def create_user(self, email, password=None):
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()
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):
user = self.create_user(email, password=password)
user.staff = True
user.save()
return user
class Emp(AbstractBaseUser):
user = models.OneToOneField(User, on_delete=models.CASCADE)
email = models.CharField(max_length=100, default=None, unique=True)
first_name = models.CharField(max_length=100, default=None, null=True)
last_name = models.CharField(max_length=100, default=None, null=True)
username = models.CharField(max_length=100, default=None, null=True)
password = models.CharField(max_length=100, default=None)
phone = models.CharField(max_length=20, default=None, null=True, blank=True)
address1 = models.CharField(max_length=100, default=None, null=True, blank=True)
address2 = models.CharField(max_length=100, default=None, null=True, blank=True)
city = models.CharField(max_length=100, default=None, null=True, blank=True)
state = models.CharField(max_length=100, default=None, null=True, blank=True)
zip = models.CharField(max_length=10, default=None, null=True, blank=True)
position = models.CharField(max_length=50, default=None)
date_hired = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now_add=True)
date_terminated = models.DateTimeField(default=None, null=True, blank=True)
status = models.SmallIntegerField(default=0)
emp_is_salary = models.BooleanField(default=False)
emp_pto_rate = models.DecimalField(max_digits=8, decimal_places=4, default=0.0)
emp_user_level = models.SmallIntegerField(default=1)
emerg_contact1 = models.CharField(max_length=100, default=None, null=True, blank=True)
emerg_contact1_phone = models.CharField(max_length=20, default=None, null=True, blank=True)
emerg_contact1_address = models.CharField(max_length=200, default=None, null=True, blank=True)
emerg_contact1_city_st = models.CharField(max_length=200, default=None, null=True, blank=True)
emerg_contact2 = models.CharField(max_length=100, default=None, null=True, blank=True)
emerg_contact2_phone = models.CharField(max_length=20, default=None, null=True, blank=True)
emerg_contact2_address = models.CharField(max_length=200, default=None, null=True, blank=True)
emerg_contact2_city_st = models.CharField(max_length=200, default=None, null=True, blank=True)
emp_note = models.TextField(default=None, null=True, blank=True)
emp_hourly_rate = models.DecimalField(max_digits=8, decimal_places=4, default=0.0)
emp_net_pto = models.DecimalField(max_digits=8, decimal_places=4, default=0.0)
emp_pto_prev = models.DecimalField(max_digits=8, decimal_places=4, default=0.0)
emp_image = models.ImageField(upload_to='media/employees/profile-pics/',
default='media/employees/profile-pics/default.png', null=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def get_full_name(self):
return f'{self.first_name} {self.last_name}'
def get_email(self):
return self.email
def __str__(self):
return self.email
def save(self, *args, **kwargs):
super(Emp, self).save(*args, **kwargs)
self.username = self.email
img = Image.open(self.emp_image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.emp_image.path)
def get_user_permissions(self, obj=None):
return True
def get_absolute_url(self):
return reverse('employees:emp-detail', args=[self.id])
objects = UserManager()
BACKENDS.PY
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
from .models import Emp
from .views import *
User = get_user_model()
class EmpBackend(ModelBackend):
supports_object_permissions = True
supports_anonymous_user = False
supports_inactive_user = False
def authenticate(self, email=None, password=None, **kwargs):
username = kwargs.get('username')
password = kwargs.get('password')
if username is None or password is None:
return
try:
user = User.objects.get(email=username)
if user.check_password(password) and self.user_can_authenticate(user):
return user
except User.DoesNotExist:
return None
return None
def user_can_authenticate(self, user):
is_active = getattr(user, 'is_active', None)
return is_active or is_active is None
def get_user(self, user_id):
try:
return Emp.objects.get(pk=user_id)
except Emp.DoesNotExist:
return None
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
SETTINGS.PY
# Login model override
AUTH_USER_MODEL = 'auth.User'
# AUTH_PROFILE_MODEL = 'employess.Emp'
LOGIN_URL = 'employees:login'
LOGIN_REDIRECT_URL = 'employees:emp-home'
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'employees.backends.EmpBackend',
]
Related
for my web-application which is made in Django and I made a custom users app for users (so I am not using the Django's user). I managed to get the users app working and I created a superuser using this command:
python manage.py createsuperuser
and got this message:
Superuser created successfully.
but when I tried to log in as the superuser in the browser, it did not work and got this error message on the browser (I tried different browsers as well):
Please enter the correct username and password for a staff account. Note that both fields may be case-sensitive.
I paid attention to case-sensitive letters. do you know what the problem could be?
here is the models.py for the users app:
import random
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core import validators
from django.utils import timezone
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager, send_mail
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, username, password, phone_number, email, is_staff, is_superuser, **extra_fields):
"""
Created and saves a User with the given username, email and password.
"""
now = timezone.now()
if not username:
raise ValueError('The given username must be set')
email = self.normalize_email(email)
user = self.model(phone_number=phone_number,
username=username, email=email,
is_staff=is_staff, is_active=True,
is_superuser=is_superuser,
date_joined=now, **extra_fields)
if not extra_fields.get('no_password'):
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username=None, phone_number=None, email=None, password=None, **extra_fields):
if username is None:
if email:
username = email.split('#', 1)[0]
if phone_number:
username = random.choice('abcdefghijklmnopqrstuvwxyz') + str(phone_number)[-7:]
while User.objects.filter(username=username).exists():
username += str(random.randint(10, 99))
return self._create_user(username, phone_number, email, password, False, False, **extra_fields)
def create_superuser(self, username, email, phone_number, password, **extra_fields):
return self._create_user(username, email, phone_number, password, True, True, **extra_fields)
def get_by_phone_number(self, phone_number):
return self.get(**{'phone_number': phone_number})
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(_('username'), max_length=32, unique=True,
help_text=
'Required. 30 characters or fewer starting with a letter. Letters, digits',
validators=[
validators.RegexValidator(r'^[a-zA-Z][a-zA-Z0-9_\.]+$',
_('Enter a valid username starting with a-z.'
'This value may contain only letters and numbers'
'and underscore characters.'), 'invalid')
],
error_messages={
'unique':_('A user with that username already exists.'),
}
)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email address'), unique=False, null=True, blank=True)
phone_number = models.BigIntegerField(_('phone number'), unique=True, null=True, blank=True,
validators=[
validators.RegexValidator(r'^319[0-3,9]\d{8}$',
('Enter a valid mobile number.'), 'egrwfk')
],
error_messages={
'unique': _('A user with this mobile phone number already exits')
}
)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text='designates whether this user can log into this admin site.')
is_active = models.BooleanField(_('active'), default=True,
help_text=_('designates whether this user should be treated as active'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
last_seen = models.DateTimeField(_('last seen date'), null=True)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'phone_number']
class Meta:
db_table = 'users'
verbose_name = _('user')
verbose_name_plural = _('users')
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 email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
#property
def is_loggedin_user(self):
return self.phone_number is not None or self.email is not None
def save(self, *args, **kwargs):
if self.email is not None and self.email.strip() == '':
self.email = None
super().save(*args, **kwargs)
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
nick_name = models.CharField(_('nick_name'), max_length=150, blank=True)
avatar = models.ImageField(_('avatar'), blank=True)
birthday = models.DateField(_('birthday'), null=True, blank=True)
gender = models.BooleanField(_('gender'), null=True, help_text='femal is False, male is True, null is unset')
province = models.ForeignKey(verbose_name=_('province'), to='Province', null=True, on_delete=models.SET_NULL)
# email = models.EmailField(_('email_address'), blank=True)
# phone_number = models.BigIntegerField(_('phone_number'), null=True, blank=True,
# validators=[
# validators=RegexValidators(r'^319[0-3,9]\d(8)$,
# _('Enter a valid mobile number'), 'invalid'),
# ],
# )
class Meta:
db_table = 'user_profiles'
verbose_name = _('profile')
verbose_name_plural = _('profiles')
#property
def get_first_name(self):
return self.user.first_name
#property
def get_last_name(self):
return self.user.last_name
def get_nick_name(self):
return self.nick_name if self.nick_name else self.user.username
class Device(models.Model):
WEB = 1
IOS = 2
ANDROID = 3
DEVICE_TYPE_CHOICES = (
(WEB, 'web'),
(IOS, 'ios'),
(ANDROID, 'android')
)
user = models.ForeignKey(User, related_name='devices', on_delete=models.CASCADE)
device_uuid = models.UUIDField(_('Device UUID'), null=True)
# notify_token = models.CharField(_('notification token'), max_length=200, blank=True,
# validators=[validators.RegexValidator(r'([a-z]|[A-z]|[0-9])\w+',
# _('Notify token is not valid'), 'invalid')]
# )
last_login = models.DateTimeField(choices=DEVICE_TYPE_CHOICES, default=ANDROID)
device_type = models.PositiveSmallIntegerField(choices=DEVICE_TYPE_CHOICES, default=ANDROID)
device_os = models.CharField(_('device os'), max_length=20, blank=True)
device_model = models.CharField(_('device model'), max_length=50, blank=True)
app_version = models.CharField(_('app version'), max_length=20, blank=True)
created_time = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'user_devices'
verbose_name = _('device')
verbose_name_plural = _('devices')
unique_together = ('user', 'device_uuid',)
class Province(models.Model):
name = models.CharField(max_length=50)
is_valid = models.BooleanField(default=True)
modified_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
I am also getting this message on the terminal:
[05/Jan/2023 13:38:44] "POST /admin/login/?next=/admin/ HTTP/1.1" 200 2374
hello i have a legacy database wiche use unix time and I have override an absractbaseuser here is my model
from django.db import models
from django.contrib.auth.models import AbstractBaseUser,BaseUserManager
from django.contrib.auth.signals import user_logged_in
from .helper import get_current_unix_timestamp
class MyUserManager(BaseUserManager):
def create_user(self, username,password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not username:
raise ValueError('user must have a username')
user = self.model(
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, password=None):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
username,
password=password,
)
user.is_admin = True
user.is_superuser = True
user.is_staff = True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
id = models.AutoField(primary_key=True,verbose_name='ID',)
username = models.CharField(max_length=50, blank=True, null=True,unique=True)
password = models.CharField(max_length=255, blank=True, null=True)
email = models.CharField(max_length=255, blank=True, null=True)
ip = models.CharField(max_length=255,null=True,blank=True)
date_registered = models.IntegerField(default=get_current_unix_timestamp())
last_login = models.IntegerField(null=True,blank=True)
member_group_id = models.IntegerField(blank=True, null=True)
credits = models.FloatField(blank=True, null=True)
notes = models.TextField(blank=True, null=True)
status = models.IntegerField(blank=True, null=True)
reseller_dns = models.TextField(blank=True, null=True)
owner_id = models.IntegerField(blank=True, null=True)
override_packages = models.TextField(blank=True, null=True)
hue = models.CharField(max_length=50, blank=True, null=True)
theme = models.IntegerField(blank=True, null=True)
timezone = models.CharField(max_length=255, blank=True, null=True)
api_key = models.CharField(max_length=64, blank=True, null=True)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
objects = MyUserManager()
USERNAME_FIELD = 'username'
class Meta:
managed = True
db_table = 'users'
ordering = ['username']
def __str__(self):
return self.username
what I have done to insert unix time in my last_login is to change behavior of django signal user_logged_in like this . the get_current_unix_timestamp() is a sample function that convert to unix timestamp
def update_last_login(sender, user, **kwargs):
"""
A signal receiver which updates the last_login date for
the user logging in.
"""
user.last_login = get_current_unix_timestamp()
user.save(update_fields=['last_login'])
user_logged_in.connect(update_last_login)
the get_current_unix_timestamp function :
import datetime
def get_current_unix_timestamp():
"""this function retrun a unix format datetime"""
return int(datetime.datetime.now().strftime('%s'))
when I try to login in Django Admin I get this error
TypeError at /admin/login/
Field 'last_login' expected a number but got datetime.datetime(2021, 12, 26, 11, 35, 3, 605827).
As per our model, you are teh IntegerField for Datetime field
try replacing
date_registered = models.IntegerField(default=get_current_unix_timestamp())
last_login = models.IntegerField(null=True,blank=True)
with
date_registered = models.DateTimeField("your settins here")
last_login = models.DateTimeField("your settins here")
I have a User model, an ApplicantProfile model, and a CompanyProfielModel. A user can be of two types, an applicant or a company.
models.py
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255)
date_joined = models.DateTimeField(auto_now_add=True)
is_applicant = models.BooleanField(default=False)
is_company = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
objects = MyUserManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
class ApplicantProfile(models.Model):
GENDER_MALE = 0
GENDER_FEMALE = 1
GENDER_CHOICES = [(GENDER_MALE, 'Male'), (GENDER_FEMALE, 'Female')]
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
image = models.ImageField(upload_to=image_directory_path, storage=image_storage, null=True, blank=True)
bio = models.TextField(max_length=500, null=True, blank=True)
address = models.TextField(max_length=200, null=True, blank=True)
birth_date = models.DateField(null=True, blank=True)
phone = PhoneNumberField(null=True, blank=True)
website = models.URLField(max_length=255, null=True, blank=True)
gender = models.IntegerField(choices=GENDER_CHOICES, null=True, blank=True)
interest = models.TextField(max_length=255, null=True, blank=True)
linkedin = models.CharField(max_length=255, null=True, blank=True)
github = models.CharField(max_length=255, null=True, blank=True)
twitter = models.CharField(max_length=255, null=True, blank=True)
facebook = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return self.user.name
class CompanyProfile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
image = models.ImageField(upload_to=image_directory_path, storage=image_storage, null=True, blank=True)
about = models.TextField(max_length=500, null=True, blank=True)
location = models.CharField(max_length=100, null=True, blank=True)
start_date = models.DateField(null=True, blank=True)
website = models.URLField(max_length=255, null=True, blank=True)
logo = models.ImageField(upload_to=image_directory_path, storage=image_storage, null=True, blank=True)
def __str__(self):
return self.user.name
I have two URLs to create two different types of users. I can create applicants automatically right after a user registers from the applicant registration url, but I can't create companies from the company registration url.
views.py
def applicant_register(request):
if request.method == 'POST':
form = ApplicantRegistrationForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email')
raw_password = form.cleaned_data.get('password1')
user = authenticate(email=email, password=raw_password)
ApplicantProfile.objects.create(user=user)
messages.success(request, "Account created successfully.")
return redirect('applicant-feed')
form = ApplicantRegistrationForm()
context = {
"form": form
}
return render(request, 'user/applicant/applicant-register.html', context)
def company_register(request):
if request.method == 'POST':
form = CompanyRegistrationForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email')
raw_password = form.cleaned_data.get('password1')
user = authenticate(email=email, password=raw_password)
CompanyProfile.objects.create(user=user) # This line gives the error
messages.success(request, "Account created successfully.")
return redirect('company-feed')
form = CompanyRegistrationForm()
context = {
"form": form
}
return render(request, 'user/company/company-register.html', context)
Any help is appreciated.
Getting this error in the browser
According to error, looks like CompanyProfile is not a model class but something else. Is there a chance that you redefine it in views.py? Probably you also define a view with this name?
you don't need to use the form because you can create an account directly to any model like this function
def company_register(request):
if request.method == 'POST':
user = request.POST['user']
image = request.FILES['image']
about = request.POST['about']
location = request.POST['location']
start_date = request.POST['start_date']
website = request.POST['website']
logo = request.FILES['logo']
profile = CompanyProfile.objects.create(user=user, image=image, about=about, location=location, start_date=start_date, website=website, logo=logo)
profile.save()
return Response('Done')
else:
return Response('POST method only accepted')
In this project, I got three types of users: ChalkSlateAdmin (this is not a superuser, administrator or staff, etc.), Student and Teacher. All of these can be considered ChalkSlateUser as each have a OneToOne Relationship with the model. ChalkSlateAdmin can be considered an institute and any time someone registers as a ChalkSlateAdmin, there is a new institute as ChalkSlateAdmin has that attribute.
Teachers and Students can join institutes (ChalkSlateAdmin attribute) that are already registered. So, I need to create a form that has choices of institutes that are currently registered.
My question is, how can I define choices that change depending on what institutes (ChalkSlateAdmin attribute) are registered? Before this, I used constant string values for choices like male & female.
models.py,
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
class MyAccountManager(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(
email=self.normalize_email(email),
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user=self.create_user(
email=self.normalize_email(email),
password=password,
username=username,
)
user.user_type = 1
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
class ChalkSlateUser(AbstractBaseUser):
# required to include
email = models.EmailField(verbose_name='email', unique=True, max_length=60)
username = models.CharField(max_length=60, unique=True)
date_joined = models.DateField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateField(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)
# new
first_name = models.CharField(max_length=60, verbose_name='first name')
last_name = models.CharField(max_length=60, verbose_name='last name')
has_institute = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username',]
objects = MyAccountManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
AUTHORITY = 1
INSTITUTE = 2
STUDENT = 3
TUTOR = 4
USER_TYPE_CHOICES = (
(AUTHORITY, 'Authority (superuser or admin)'),
(INSTITUTE, 'ChalkSlateAdmin'),
(STUDENT, 'Student'),
(TUTOR, 'Tutor'),
)
user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES, null=True, blank=True)
# user_type = models.PositiveSmallIntegerField(null=True, blank=True)
# is_admin = models.BooleanField(default=False)
# is_student = models.BooleanField(default=False)
# is_tutor = models.BooleanField(default=False)
class ChalkSlateAdmin(models.Model):
chalkslate_user = models.OneToOneField(ChalkSlateUser, on_delete=models.CASCADE, null=True)
# username_institute = models.CharField(max_length=100, unique=True)
institute_name = models.CharField(verbose_name='institute name', max_length=100, unique=True)
institute_details = models.CharField(verbose_name='institute details', max_length=100)
def __str__(self):
return self.chalkslate_user.email
class Student(models.Model):
chalkslate_user = models.OneToOneField(ChalkSlateUser, on_delete=models.CASCADE)
# username_student = models.CharField(max_length=100, unique=True)
# name = models.CharField(max_length=100)
student_details = models.CharField(verbose_name='student details', max_length=100)
picture = models.ImageField(verbose_name='picture', upload_to='student_pictures')
def __str__(self):
return self.chalkslate_user.email
class Tutor(models.Model):
chalkslate_user = models.OneToOneField(ChalkSlateUser, on_delete=models.CASCADE)
# username_tutor = models.CharField(max_length=100, unique=True)
# name = models.CharField(max_length=100)
tutor_details = models.CharField(verbose_name='tutor details', max_length=100)
picture = models.ImageField(verbose_name='picture', upload_to='tutor_pictures')
def __str__(self):
return self.chalkslate_user.email
# make the ins_tutor and ins_student models
class InsStudent(models.Model):
institute = models.ForeignKey(ChalkSlateAdmin, on_delete=models.CASCADE)
student = models.OneToOneField(Student, on_delete=models.CASCADE)
roll = models.IntegerField()
class_year = models.CharField(max_length=50)
section = models.CharField(max_length=50)
class Meta:
unique_together = ('roll', 'class_year', 'section',)
class InsTutor(models.Model):
institute = models.ForeignKey(ChalkSlateAdmin, on_delete=models.CASCADE)
tutor = models.OneToOneField(Tutor, on_delete=models.CASCADE)
class notice(models.Model):
name=models.CharField(max_length=50,null=False)
mail=models.CharField(max_length=50,null=False)
date=models.DateTimeField(null=False)
content=models.CharField(max_length=200,null=False)
per=models.CharField(max_length=50,default='no')
def __str__(self):
return self.name
For choices option, you can set a method that returns a list with what you want in it.
For instance, for a BankCard model I implemented in one of my projects, I did something similar to what you want to achieve, for the expiration_year. See below :
class BankCard(models.Model):
def _years(year):
return [(year, str(year)) for year in range(year, year + 10)]
expiration_year = models.IntegerField(choices=_years(datetime.datetime.now().year))
Maybe you could do something similar.
I've built a custom user model called "Administrator" for superuser purpose, and the other model called "Customer" for normal user purpose.
I intended to separate them into two different tables, it partly worked but not perfectly. The problem is that when I created an instance for Customer, the instance will be automatically added into the Administrators table, this isn't what I want.
Administrator model on Django admin site
Customer model on Django admin site
Administrator model shown below:
class Administrator(PermissionsMixin, AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
join_date = models.DateField(auto_now_add=True, editable=False)
objects = AdministratorManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.get_full_name()
#property
def is_staff(self):
return self.is_admin
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
Customer model shown below:
class Customer(Administrator):
first_name = models.CharField(max_length=255, default='', blank=False)
last_name = models.CharField(max_length=255, default='', blank=False)
DOB = models.DateField()
security_question1 = models.CharField(max_length=500, default='', blank=False)
security_question2 = models.CharField(max_length=500, default='', blank=False)
security_question_answer1 = models.CharField(max_length=500, default='', blank=False)
security_question_answer2 = models.CharField(max_length=500, default='', blank=False)
# REQUIRED_FIELDS = ['email', 'first_name', 'last_name', 'DOB', 'security_question1', 'security_question2']
is_active = True
is_admin = False
You are wrongly inherited the Customer model. It should be inherited from AbstractBaseUser as
class Customer(AbstractBaseUser):
#Your code
UPDATE-1
You can use Abstract class for inheriting.
Define a base class as Abstract and inherit from that class might help you
class BaseClass(PermissionsMixin, AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
join_date = models.DateField(auto_now_add=True, editable=False)
objects = AdministratorManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.get_full_name()
#property
def is_staff(self):
return self.is_admin
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
class Meta:
abstract = True
class Administrator(BaseClass):
pass
class Customer(BaseClass):
first_name = models.CharField(max_length=255, default='', blank=False)
last_name = models.CharField(max_length=255, default='', blank=False)
DOB = models.DateField()
security_question1 = models.CharField(max_length=500, default='', blank=False)
security_question2 = models.CharField(max_length=500, default='', blank=False)
security_question_answer1 = models.CharField(max_length=500, default='', blank=False)
security_question_answer2 = models.CharField(max_length=500, default='', blank=False)
# REQUIRED_FIELDS = ['email', 'first_name', 'last_name', 'DOB', 'security_question1', 'security_question2']
is_active = True
is_admin = False