I have created a custom user application.
My custom user extends AbstractBaseUser...
In my settings file:
AUTH_USER_MODEL = 'custom_auth.CustomUser'
My custom user:
class CustomUser(AbstractBaseUser, PermissionsMixin):
DEGREE_CHOICES = zip( range(1,34), range(1,34) )
class Meta:
verbose_name = "user"
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
db_index=True,
)
poster = models.ImageField(upload_to='users/poster/', blank=True, null=True)
first_name = models.CharField(max_length=80)
last_name = models.CharField(max_length=100 )
chapter = models.CharField(max_length=100 )
lodge = models.CharField(max_length=100 )
degree = models.IntegerField(max_length=2, choices=DEGREE_CHOICES )
country = models.CharField(max_length=100, blank=True, null=True)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the 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. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
#REQUIRED_FIELDS = ['user_name' ]
Now I am changing a lot of fields on custom_auth's models.py and trying to migrate it.
The fields that i have changed not changes at the database but newly added fields are added at the database.
How can i migrate a custom user properly? Am i doing something wrong?
Related
Well I'm trying to create user addition form from frontend that creates user and additional info based on custom user model.But I'm getting duplicate key value violates unique constraint "users_driver_email_key" DETAIL: Key (email)=() already exists.
here is my code:
Models.py
class CustomUser(AbstractUser):
is_driver = models.BooleanField(default=False)
is_accountant = models.BooleanField(default=False)
is_dispatcher = models.BooleanField(default=False)
class Driver(models.Model):
driver_user = models.OneToOneField(CustomUser, on_delete = models.CASCADE, primary_key = True)
full_name = models.CharField(max_length=50, default=None)
phone_number = models.CharField(max_length=50, default=None)
email = models.EmailField(unique=True,max_length=255, default=None)
address = models.CharField(max_length=70, default=None)
country = models.CharField(max_length=50, default=None)
state = models.CharField(choices=US_STATES,max_length=50, default=None)
city = models.CharField(max_length=50, default=None)
zipp = models.CharField(max_length=50, default=None)
birth_date = models.DateField(default=None)
license_no = models.IntegerField(default=None)
license_exp_date = models.DateField(default=None)
last_medical = models.DateField(default='', blank=True, null=True)
next_medical = models.DateField(default='', blank=True, null=True)
last_drug_test = models.DateField(default='', blank=True, null=True)
next_drug_test = models.DateField(default='', blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
date_edited = models.DateTimeField(auto_now=True)
status = models.IntegerField(choices=STATUS, default=1)
class DriversFiles(models.Model):
file = models.FileField(upload_to="media/", blank=True, null=True)
driver_files = models.ForeignKey('Driver', on_delete=models.CASCADE, default=None, null=True)
#receiver(post_save, sender=CustomUser)
def create_user_profile(sender, instance, created, **kwargs):
# if Created is true (Means Data Inserted)
if created:
# Check the user_type and insert the data in respective tables
if instance.is_driver:
Driver.objects.create(
driver_user=instance,
full_name = "123",
phone_number = "123",
email = "",
address = "123",
country = "123",
state = "123",
city = "123",
zipp = "213",
birth_date = '2022-01-01',
license_no = '1234',
license_exp_date = '2022-01-01',
last_medical= '2022-01-01',
next_medical = '2022-01-01',
last_drug_test = '2022-01-01',
next_drug_test = '2022-01-01',
)
Views.py
def create_driver_view(request):
if request.method == "POST":
add_driver = DriverForm(request.POST)
add_driver_file = request.FILES.getlist("file")
if add_driver.is_valid():
#For Custom User
password = 'Ga20224$5%'
full_name = add_driver.cleaned_data['full_name']
email = add_driver.cleaned_data['email']
phone_number = add_driver.cleaned_data['phone_number']
address = add_driver.cleaned_data['address']
country = add_driver.cleaned_data['country']
state = add_driver.cleaned_data['state']
city = add_driver.cleaned_data['city']
zipp = add_driver.cleaned_data['zipp']
birth_date = add_driver.cleaned_data['birth_date']
license_no = add_driver.cleaned_data['license_no']
license_exp_date = add_driver.cleaned_data['license_exp_date']
last_medical = add_driver.cleaned_data['last_medical']
next_medical = add_driver.cleaned_data['next_medical']
last_drug_test = add_driver.cleaned_data['last_drug_test']
next_drug_test = add_driver.cleaned_data['next_drug_test']
print(email)
username = email.split('#')[0] + uuid.uuid4().hex[:2]
user = CustomUser.objects.create_user(
username = username,
password = password,
is_driver = True,
email = email
)
#For Driver Profile
user.driver.full_name = full_name
user.driver.email = email
user.save()
# for i in add_driver_file:
# DriversFiles.objects.create(driver_files=user, file=i)
return redirect('drivers:list_driver')
else:
print(add_driver.errors)
else:
add_driver = DriverForm()
add_driver_files = DriverFormUpload()
return render(request, "drivers/add.html", {"add_driver": add_driver, "add_driver_files": add_driver_files})
I was getting eror {{message}} that username or email is already taken but now it opens debugger. In addition it creates user account with the same emails but then dont creates Driver table cause email is not unique.
I'm new in django and Just wanted to create custom user models, but there is so many headaches. What should I do here. or how can I create custom user models correctly
As you are inheriting from AbstractUser class (see line 334), you already have an email field on your user instance. Thus, removing the email field from the driver model should fix your issue.
class AbstractUser(AbstractBaseUser, PermissionsMixin):
"""
An abstract base class implementing a fully featured User model with
admin-compliant permissions.
Username and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator()
username = models.CharField(
_("username"),
max_length=150,
unique=True,
help_text=_(
"Required. 150 characters or fewer. Letters, digits and #/./+/-/_ only."
),
validators=[username_validator],
error_messages={
"unique": _("A user with that username already exists."),
},
)
first_name = models.CharField(_("first name"), max_length=150, blank=True)
last_name = models.CharField(_("last name"), max_length=150, blank=True)
email = models.EmailField(_("email address"), blank=True)
If you want to use the email field as auth and unique, you could approach it like so:
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _
from .managers import CustomUserManager
class CustomUser(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
Django provided to facilities to customize the Default USER Model.
Have Two Famous approaches...
1 - Extending User Model Using a Custom Model Extending AbstractUser
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
profile_pic = models.ImageField(upload_to ='/Propife/',null=True, blank=True)
2 - Extending User Model Using a Custom Model Extending AbstractBaseUser
from django.db import models
from django.core.mail import send_mail
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _
from .managers import UserManager
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
date_joined = models.DateTimeField(_('date joined'), auto_now_add=True)
is_active = models.BooleanField(_('active'), default=True)
profile_pic = models.ImageField(upload_to ='/Propife/',null=True, blank=True)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
NOTE:- put all fields with null=True blank=True which you want to use for profile purpose. and create a form with CustomUserModel and then write the Update functionality for profile fields which leave with null=True blank=True.
I used the django debug toolbar to analyse why the calls to my usermodel were so painfully slow within the django admin. There I saw that I had hundreds of duplicate calls to the content_type model:
SELECT ••• FROM "django_content_type" WHERE "django_content_type"."id"
= 1 LIMIT 21
362 similar queries. Duplicated 4 times.
To be honest, I do not understand where these calls come from in the first place but I wanted to pre_fetch the model. However, this seems not to be possible in the normal way because there is actually no ForeignKey or any other kind of direct relationship between the models. How could I reduce those 362 content_type calls?
This is the usermodel in question:
class User(AbstractBaseUser, PermissionsMixin):
"""
Base model for the user application
"""
USERNAME_FIELD = "email"
objects = UserManager()
username_validator = None
username = None
email = models.EmailField(_("email address"), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
first_name = models.CharField(max_length=150, blank=True)
last_name = models.CharField(max_length=150, blank=True)
title_of_person = models.ForeignKey(
TitleOfPerson, on_delete=models.CASCADE, blank=True, null=True
)
is_verified = models.BooleanField(default=False)
language = models.ForeignKey(
Language, blank=True, null=True, on_delete=models.SET_NULL
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = _("User")
verbose_name_plural = _("Users")
def __str__(self) -> str:
return self.email
Thanks
class FutsalUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(
_('staff status'),
default=True,
help_text=_('Designates whether the user can log into this admin site.'),
)
objects = FutsalUserManager()
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
#property
def company_details(self):
company_data = Company.objects.filter(user= self)
if company_data :
company_data.name
return company_data
else:
return None
class Company(TimeStampedModel):
name = models.CharField(max_length=200)
hr_name = models.CharField(max_length=200)
hr_email = models.CharField(max_length=200)
user = models.ForeignKey(
settings.AUTH_USER_MODEL, models.DO_NOTHING)
hr_verified = models.BooleanField(default=False, blank=True)
primary_phone = models.CharField(null=True, max_length=200)
followed_by = models.CharField(max_length=200,default="Not assigned")
comments = models.TextField(default="")
def __str__(self):
return self.name
1. There is no need to create a custom function in Model, to fetch other values of other table which are in relation.
[ 1 ] you should have a related_name in your company user table. like
user = models.ForeignKey(
settings.AUTH_USER_MODEL, models.DO_NOTHING, related_name='company')
# you can name company with something of your own choice.
# following will be more appropriate.
user = models.ForeignKey(
FutsalUser, models.DO_NOTHING, related_name='company')
[ 2 ] once you have a related_name, you can fetch the companies values as following.
FutsalUser.objects.all().values('email', 'is_active', 'company__name', 'company__hr_email')
2. Apart from that you can fetch the details from Company table instead.
Company.objects.all().values('name', 'user__email') # you can add more field if you want.
3
users = FatalUser.objects.all()
for user in users:
company_list = user.company_details
# this company_list will have the companies associated with user.
print(company_list)
for company in company_list:
print(company.name, company.hr_email)
I am fairly new to Django. Using Django 1.9 i created a custom user model and extended it with Profile model by sub-classing custom user model.
models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), max_length=255, unique=True, db_index=True)
is_staff = models.BooleanField(_('staff status'), default=False, help_text=_('Designates whether the user can log into this admin site.'))
is_active = models.BooleanField(_('active'), default=USERS_AUTO_ACTIVATE,
help_text=_('Designates whether this user should be treated as active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
first_name = models.CharField(_('first name'), max_length=255, null=True, blank=True)
last_name = models.CharField(_('last name'), max_length=255, null=True, blank=True)
username = models.CharField(_('username'), max_length=100, unique=True, db_index=True, null=True, blank=True)
mobile = models.CharField(_('mobile phone'), max_length=15, unique=True, null=True, blank=True)
objects = UserInheritanceManager()
base_objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = _('User')
verbose_name_plural = _('Users')
class Profile(User, TimeStampedModel):
gender_choices = (
('M', 'Male'),
('F', 'Female'),
)
gender = models.CharField(_('gender'), max_length=1, choices=gender_choices, null=True, blank=True)
profile_image = models.ImageField(_('profile image'), upload_to=create_image_path, null=True, blank=True)
class Meta:
verbose_name = _('User Profile')
verbose_name_plural = _('Users Profile')
Here are the code snippet from my admin.py file
from django.contrib import admin, messages
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import Profile as UserProfile
from django.contrib.auth import get_user_model
class UserProfileAdmin(admin.TabularInline):
model = UserProfile
max_num = 1
can_delete = False
class UserAdmin(BaseUserAdmin):
inlines = [ UserProfileAdmin, ]
User = get_user_model()
admin.site.register(User, UserAdmin)
When i try to edit a user in django admin it displays the User Model fields like password, username, email etc in UserProfile screen as well i.e twice. I am not able to figure out why this is happening. Isn't these fields should be displayed once only. Any help is appreciated.
This is my User class:
class User(TimeStampedModel, AbstractBaseUser):
name = models.CharField(null=False, max_length=255)
username = models.CharField(null=False, unique=True, max_length=255)
email = models.EmailField(null=True)
mobile_number = models.CharField(null=True, max_length=255)
bio = models.CharField(null=True, max_length=255)
title = models.CharField(null=True, max_length=255)
posts = models.IntegerField(default=0)
views = models.IntegerField(default=0)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
last_active_on = models.DateTimeField(auto_now=True)
objects = CustomUserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['name']
When I try to update the user from admin dashboard I get 'field cannot be empty error' for the following fields: mobile_number, email, bio, title
Any idea on how to resolve this?
Specify blank=True in your model for those fields.
class User(TimeStampedModel, AbstractBaseUser):
name = models.CharField(null=False, max_length=255)
username = models.CharField(null=False, unique=True, max_length=255)
email = models.EmailField(null=True, blank=True) # add 'blank' argument
mobile_number = models.CharField(null=True, max_length=255, blank=True) # add 'blank' argument
bio = models.CharField(null=True, max_length=255, blank=True) # add 'blank' argument
title = models.CharField(null=True, max_length=255, blank=True) # add 'blank' argument
posts = models.IntegerField(default=0)
views = models.IntegerField(default=0)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
last_active_on = models.DateTimeField(auto_now=True)
objects = CustomUserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['name']
If a field has blank=True, form validation will allow entry of an empty value. Default value for blank argument is False.
Note: null is purely database-related, whereas blank is validation-related.
If a field has blank=True, form validation will allow entry of an empty value.
If a field has null=True, Django will store empty values as NULL in the database.