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.
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'm attempting to build out a rather large "Patient Onboarding" form using ModelForms.
I'm having trouble getting the choices within the foreign keys to appear in the admin area or to the rendered form without manually adding them to the Postgres database.
There has got to be a more efficient way to be doing this...thanks in advance!
#models.py
from django.db import models
from django.forms import ModelForm
from django import forms
class Patient(models.Model):
first_name = models.CharField(max_length=30, verbose_name='First Name', blank=False)
middle_name = models.CharField(max_length=30, verbose_name='Middle Name', blank=False)
last_name = models.CharField(max_length=30, verbose_name='Last Name', blank=False)
gender = models.ForeignKey('GenderChoices', on_delete=models.CASCADE, verbose_name='Gender', blank=False)
date_of_birth = models.DateField(verbose_name='Date of Birth', blank=False)
medications = models.ForeignKey('MedicationsYesNo', on_delete=models.CASCADE, verbose_name='Do you currently take any medications?', blank=False)
class MedicationsYesNo(models.Model):
medications_yes_no = models.CharField(
max_length=100,
choices = [
('Yes', 'Yes'),
('No', 'No')
]
)
def __str__(self):
return self.medications_yes_no
class OnboardingForm(ModelForm):
class Meta:
model = Patient
fields = '__all__'
I have the following two models:
class CustomUser(AbstractUser):
objects = CustomUserManager()
class Meta:
ordering = ['nin']
verbose_name = 'User'
verbose_name_plural = 'Users'
username = None
name = models.CharField(max_length=50)
nin = models.CharField(verbose_name= 'National Insurance Number', max_length=9, unique=True, null=False, blank=False, validators=[RegexValidator(regex='^[a-zA-Z]{2}[0-9]{6}[a-zA-Z]{1}$', message='National Insurance Number consists of two letters, followed by six numbers, followed by one letter.')])
email = models.EmailField(verbose_name='E-Mail', unique=True)
id_document = models.FileField(verbose_name='ID Document', upload_to='user_id_documents', help_text='E.G. Scan of passport, driving licence etc.')
address_document = models.FileField(verbose_name='Proof Of Address', upload_to='user_address_documents', help_text='E.G. Utility bill etc.')
is_validated = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'nin', 'id_document', 'address_document', 'is_validated']
class UserAddress(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.PROTECT)
name_num = models.CharField(max_length=30, null=False, unique=False, blank=False)
street = models.CharField(max_length=30, null=False, unique=False, blank=False)
postcode = models.CharField(max_length=10, null=False, unique=False, blank=False)
And the following two forms:
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = ('email', 'name', 'nin', 'id_document', 'address_document')
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ('email', 'name', 'nin', 'id_document', 'address_document')
These forms successfully create/modify a CustomUser object, but do not make any mention of the UserAddress model. In the admin, I am using an inline to give/modify the UserAddresses, but this does not work in a signup form.
Should I modify CustomUser to have a foreignkey to UserAddress? This seems like it would be circular...
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 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?