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.
Related
I'm building an import excel files system for every leads whit an import-export library. On the Website, each user must be able to import his leads and make sure that they are viewed only by him. In all other cases, I filtered the "organisation" field linked to a UserProfile model through the views.py. But now I don't know how to filter the field organisation for a specific user. At the moment I can import the excel files from the template but leave the organisation field blank. Help me please I'm desperate
Models.py
class Lead(models.Model):
nome = models.CharField(max_length=20)
cognome = models.CharField(max_length=20)
luogo=models.CharField(max_length=50, blank=True, null=True, choices=region_list)
città=models.CharField(max_length=20)
email = models.EmailField()
phone_number = models.CharField(max_length=20)
description = models.TextField()
agent = models.ForeignKey("Agent", null=True, blank=True, on_delete=models.SET_NULL)
category = models.ForeignKey("Category", related_name="leads", null=True, blank=True, on_delete=models.SET_NULL)
chance=models.ForeignKey("Chance",related_name="chance", null=True, blank=True, on_delete=models.CASCADE)
profile_picture = models.ImageField(null=True, blank=True, upload_to="profile_pictures/")
converted_date = models.DateTimeField(null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
organisation = models.ForeignKey(UserProfile, on_delete=models.CASCADE,null=True, blank=True)
objects = LeadManager()
age = models.IntegerField(default=0)
def __str__(self):
return f"{self.nome} {self.cognome}"
class User(AbstractUser):
is_organisor = models.BooleanField(default=True)
is_agent = models.BooleanField(default=False)
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
Views.py
def simple_upload(request):
if request.method == 'POST':
Lead_resource = LeadResource()
dataset = Dataset()
newdoc = request.FILES['myfile']
imported_data = dataset.load(newdoc.read(),format='xlsx')
#print(imported_data)
for data in imported_data:
value = Lead(
data[0],
data[2],#nome
data[3],#cognome
data[5],#luogo
data[7],#città
data[8],#email
data[9],#numero telefono
data[11],#desc
)
value.save()
result = Lead_resource.import_data(dataset, dry_run=True) # Test the data import
if not result.has_errors():
Lead_resource.import_data(dataset,dry_run=False) # Actually import now
return render(request, 'input.html')
Resources.py
class LeadResource(resources.ModelResource):
nome = fields.Field(attribute='nome', column_name='nome')
luogo = fields.Field(attribute='luogo', column_name='regione')
class Meta:
model = Lead
report_skipped=True
admin.py
#admin.register(Lead)
class PersonAdmin(ImportExportModelAdmin):
readonly_fields = ('date_added',)
I am working with a database that stores sex as 0 - male and 1 - female.
My forms.py looks like this
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = TbUser
def clean_username(self):
username = self.cleaned_data["username"]
try:
TbUser.objects.get(username=username)
except TbUser.DoesNotExist:
return username
raise forms.ValidationError(self.error_messages['duplicate_username'])
class TbUserRegisterForm(CustomUserCreationForm):
email = forms.EmailField()
class Meta:
model = TbUser
fields = ['username', 'email', 'cellphone', 'sex', 'role', 'department', 'password1', 'password2']
Django user model
class TbUser(AbstractBaseUser, PermissionsMixin):
id = models.CharField(primary_key=True, max_length=32, default=uuid.uuid4)
username = models.CharField(max_length=40, blank=True, null=True, unique=True, db_column='usname')
password = models.CharField(max_length=255, blank=True, null=True, db_column='dj_psword')
email = models.CharField(max_length=255, blank=True, null=True)
cellphone = models.CharField(max_length=100, blank=True, null=True)
image_id = models.CharField(max_length=40, blank=True, null=True)
sex = models.IntegerField(blank=True, null=True)
is_available = models.IntegerField(blank=True, null=True)
role = models.ForeignKey(TbRole, on_delete=models.CASCADE)
department = models.ForeignKey(TbDepartment, on_delete=models.CASCADE)
is_superuser = models.BooleanField(default=False, blank=True, null=True, db_column='default_super')
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
objects = TbUserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
managed = False
db_table = 'tb_user'
def __str__(self):
return '%s' % self.username
Since sex is an integer field, the UI form field is not a choice field but just showing arrows for incrementing the integer. Is there a way to make it a choice field that for m will store 0 and f - 1?
Yes, you can assign this to the choices=… parameter [Django-doc]:
SEX_CHOICES = [
(0, 'Male')
, (1, 'Female')
]
class TbUser(AbstractBaseUser, PermissionsMixin):
# …
sex = models.IntegerField(blank=True, null=True, choices=SEX_CHOICES)
# …
I tried to create a custom login for Django, and one of the fields in
User(AbstractBaseUser)
class User(AbstractBaseUser):
user_email = models.EmailField(verbose_name='Email right here', max_length=70, unique=True, primary_key=True)
password = models.CharField(max_length=256)
password_salt = models.CharField(max_length=15)
create_date = models.DateTimeField(auto_now=True)
role = models.ForeignKey(Roles, on_delete=models.PROTECT)
info = models.ForeignKey(PersonalInfo, on_delete=models.CASCADE)
USERNAME_FIELD = 'user_email' #username
REQUIRED_FIELDS = [info.lastname, info.firstname] #email and pass is required by defaut
object = UserManager()
def __str__(self):
"""
Return user email
"""
return self.user_email
def get_email(self):
"""
Return user email
"""
return self.user_email
def get_info(self):
"""
return user info
"""
return self.info
I have my PersonalInfo model like this:
class PersonalInfo(models.Model):
id = models.AutoField(primary_key=True)
work_email = models.EmailField(verbose_name=' email', blank=True)
email = models.EmailField(blank=True)
lastname = models.CharField(max_length=50, db_column='Last name', verbose_name="Last name")
firstname = models.CharField(max_length=50, db_column='First name', verbose_name="First name")
address = models.CharField(max_length=255, null=True, blank=True)
work_phone = models.CharField(max_length=20, null=True, blank=True, db_column='Work Phone', unique=True)
cell_phone = models.CharField(max_length=20, null=True, blank=True, db_column='Cell Phone', unique=True)
home_phone = models.CharField(max_length=20, null=True, blank=True, db_column='Home Phone', unique=True)
note = models.CharField(max_length=1000, null=True, blank=True)
class Meta:
db_table = 'PersonalInfo'
def __str__(self):
"""
return lastname and firstname
"""
return self.firstname + ' , '+ self.lastname
and I got this ERROR:
REQUIRED_FIELDS = [info.lastname, info.firstname]
AttributeError: 'ForeignKey' object has no attribute 'lastname'
How can I include info.lastname and info.firstname in REQUIRED_FIELDS?
I have three user types in user model(create, query and common), multiple type user's authority is messy when I am changing user profile with UpdateView, for example, a user who is admin, when admin clicked a user who is common user, then that user in page is in common user's authority, my UpdateView is as below:
class UserUpdateView(UpdateView):
model = User
form_class = UserForm
context_object_name = 'user'
template_name = 'general/teachers/user_change_form.html'
def get_object(self):
return get_object_or_404(User, pk=self.kwargs['pk'])
models of user:
class User(AbstractUser):
name = models.CharField(max_length=100, verbose_name="姓名", default="", blank=True)
gender = models.CharField(
max_length=7,choices=(("male","男"),("female","女")),
default="female", verbose_name="性别",
)
department = models.ForeignKey(
Department,
on_delete=models.CASCADE, null=True, blank=True, verbose_name="所属部门",
)
job_title = models.CharField(max_length=100, verbose_name="职位", default="", blank=True)
mobile = models.CharField(max_length=11, verbose_name="手机号", default="", blank=True)
email = models.EmailField(max_length=50, verbose_name="邮箱", default="", blank=True)
is_employee = models.BooleanField(default=True, verbose_name='是否是普通用户')
is_teacher = models.BooleanField(default=False, verbose_name='是否是查询用户')
is_supervisor = models.BooleanField(default=False, verbose_name='是否是评测人')
add_time = models.DateTimeField(auto_now=True, verbose_name="添加时间")
forms of user:
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'department', 'gender', 'job_title', 'email', 'mobile')
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.