Setting password for user model in the admin page - django

I created a custom User model with multiple roles customers, and employees, where employees also are in different roles: Drivers and administration.
I extended AbstractBaseUser model class to set a customized user model as this:
class UserAccountManager(BaseUserManager):
def create_superuser(self, email, first_name, last_name, password, **other_fields):
other_fields.setdefault("is_staff", True)
other_fields.setdefault("is_superuser", True)
other_fields.setdefault("is_active", True)
other_fields.setdefault("is_driver", True)
other_fields.setdefault("is_customer", True)
other_fields.setdefault("is_responsable", True)
if other_fields.get("is_staff") is not True:
raise ValueError(_("Superuser must be assigned to is_staff."))
if other_fields.get("is_superuser") is not True:
raise ValueError(_("Superuser must be assigned to is_superuser."))
return self.create_user(email, first_name, last_name, password, **other_fields)
def create_user(self, email, first_name, last_name, password, **other_fields):
if not email:
raise ValueError(_("You must provide an email address"))
email = self.normalize_email(email)
user = self.model(email=email, first_name=first_name, last_name=last_name, **other_fields)
user.set_password(password)
user.save()
return user
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_("Email Address"), unique=True)
first_name = models.CharField(_("First Name"), max_length=150, unique=True)
last_name = models.CharField(_("Last Name"), max_length=150, unique=True)
mobile = models.CharField(_("Mobile Number"), max_length=150, blank=True)
is_active = models.BooleanField(_("Is Active"), default=False)
is_staff = models.BooleanField(_("Is Staff"), default=False)
is_driver = models.BooleanField(_("Is Driver"), default=False)
is_responsable = models.BooleanField(_("Is Responsable"), default=False)
is_customer = models.BooleanField(_("Is Customer"), default=False)
created_at = models.DateTimeField(_("Created at"), auto_now_add=True, editable=False)
updated_at = models.DateTimeField(_("Updated at"), auto_now=True)
objects = UserAccountManager()
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["first_name", "last_name"]
class Meta:
verbose_name = "Account"
verbose_name_plural = "Accounts"
def __str__(self):
return self.first_name
and I created two types of models the extend this model which represent each on a different role and inherit from User model:
class Employee(User):
registration_number = models.PositiveSmallIntegerField(_("Driver Registration Number"), unique=True)
picture = models.ImageField(
verbose_name=_("Driver Pic"), help_text=_("Driver Identity Picture"), upload_to="images/driver/"
)
birth_date = models.DateField(_("Date Birth of the Driver"))
city_id = models.ForeignKey("City", blank=True, null=True, on_delete=models.SET_NULL)
bank_id = models.ForeignKey("Bank", blank=True, null=True, on_delete=models.SET_NULL)
class Meta:
verbose_name = "Employee"
verbose_name_plural = "Employees"
def __str__(self):
return self.first_name + " " + self.last_name
class Customer(User):
company_name = models.CharField(_("Company Name"), max_length=150, unique=True)
website = models.CharField(_("Company website"), max_length=150, unique=True)
mobile_2 = models.CharField(_("Mobile Number"), max_length=150, blank=True)
class Meta:
verbose_name = "Customer"
verbose_name_plural = "Customers"
def __str__(self):
return self.first_name + " " + self.last_name
I want to register the models in the admin.py:
#admin.register(User)
class UserAdmin(admin.ModelAdmin):
pass
admin.site.register(Customer)
admin.site.register(Employee)
the problem is that, when I try to add a user from the admin page, I can't set a password for this user, I have a password field that appear when I want to add a new user in any model, but the field seems to be as any normal InputText, the password is visible when it's tapped, and no password is registered in the database.
I would like to add two type of Employee in the model.py :
class Responsable(Employee):
responsability_type = models.CharField(max_length=4, blank=True)
class Meta:
verbose_name = "Responsable"
verbose_name_plural = "Responsables"
def __str__(self):
return self.first_name + " " + self.last_name
class Driver(Employee):
driving_licence = models.ImageField(
verbose_name=_("Driver Licence"), help_text=_("Driver Licence Picture"), upload_to="images/driver_licence/"
)
driver_licence_expiration_date = models.DateField(_("Expiration Date for Driver Licence"))
class Meta:
verbose_name = "Driver"
verbose_name_plural = "Drivers"
def __str__(self):
return self.first_name + " " + self.last_name
I don't know if it's a good idea to design this models for this kind of roles, I want to avoid getting multiple tables with passwords stored in it.

Don' t use model inheritance like that, especially for the custom User model. Creates a unique model that inherits from AbstractBaseUser, that contains the type of the user and that contains all the fields that you have declared in your current tables:
class User(AbstractBaseUser, PermissionsMixin):
class UserTypes(Enum):
customer = ('cu', 'Customer')
responsable = ('re', 'Responsable')
driver = ('dr', 'Driver')
#classmethod
def get_value(cls, member):
return cls[member].value[0]
user_type = models.CharField(max_length=2, choices=[x.value for x in UserTypes])
# Insert fields that are in common between all user types, for example:
email = models.EmailField(_("Email Address"), unique=True)
# Insert fields that could be None depending on the user type, for example:
company_name = models.CharField(_("Company Name"), max_length=150, unique=True, null=True, blank=True)
Then add this in your settings:
AUTH_USER_MODEL = 'yourappname.User'
Your ModelAdmin for managing users should inherit from UserAdmin to allow password management:
#admin.register(User)
class UserAdmin(UserAdmin):
fieldsets = ((None, {'fields': ('email', 'password', 'user_type', 'company_name')})) # Other fields showed when updating an user
add_fieldsets = ((None, {'fields': ('email', 'password', 'user_type', 'company_name')})) # Other fields showed when creating an user

Related

All usernames are indicated by the username phrase

admin dashboard:
In addition to the admin part, the template is displayed in the same way.
Ever since I customized the accounts section, in all the sections where I have used the username, there is a problem that the usernames are displayed without that name and only by displaying the phrase username.
settings.py:
AUTH_USER_MODEL = 'accounts.CustomUser'
models.py(accounts):
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, 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),
username=username,
password=password,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
def get_profile_image_filepath(self, filepath):
return f'images/accounts/profiles/{self.pk}/{"profile.png"}'
class CustomUser(AbstractBaseUser, PermissionsMixin):
class Meta:
permissions = [
('all', 'all of the permissions')
]
first_name = models.CharField(max_length=30, null=True, blank=True)
last_name = models.CharField(max_length=30, null=True, blank=True)
email = models.EmailField(verbose_name='email', max_length=100, unique=True)
username = models.CharField(max_length=55, unique=True)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(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)
profile_image = models.ImageField(null=True, blank=True, upload_to=get_profile_image_filepath, default='images/accounts/profiles/default_image.jpg')
objects = MyAccountManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
def __str__(self):
return self.USERNAME_FIELD
def get_profile_image_filename(self):
return str(self.profile_image)[str(self.profile_image).index(f'images/accounts/profiles/{self.pk}/'):]
def get_absolute_url(self):
return reverse("accounts:user_view", args=[str(self.id)])
models.py(news):
class News(models.Model):
class Meta:
permissions = [
('all', 'all of the permissions')
]
ordering = ['-date']
title = models.CharField(max_length=255)
header_image = models.ImageField(null=True, blank=True, upload_to="images/news/header/")
body = RichTextUploadingField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
category = models.ManyToManyField(Category, default='cryptocurrency', related_name='category')
like_news = models.ManyToManyField(AUTH_USER_MODEL, blank=True, related_name='the_news')
unlike_news = models.ManyToManyField(AUTH_USER_MODEL, blank=True, related_name='the_news_unlike')
def total_likes(self):
return self.like_news.count()
def total_unlikes(self):
return self.unlike_news.count()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("news_detail", args=[str(self.id)])
Which part of the code is wrong that shows the username like this?
You need to return self.username, not self.USERNAME_FIELD:
class CustomUser(AbstractBaseUser, PermissionsMixin):
# …
USERNAME_FIELD = 'username'
def __str__(self):
return self.username
or if you want to return the attribute with the USERNAME_FIELD, you can use the getattr(…) function [Python-doc]:
class CustomUser(AbstractBaseUser, PermissionsMixin):
# …
USERNAME_FIELD = 'username'
def __str__(self):
return getattr(self, self.USERNAME_FIELD)

How to access reverse relationship in django models?

I have two models one for User and another for storing CustomerInfo(user of type customer).
class User(AbstractBaseUser):
"""
This is a class for user table which overrides functionalities of default django user model.
Attributes:
name (CharField): Name of a user.
email (EmailField): Email address of a user.
mobile (CharField): Phone number of a user.
date_joined (CharField): When a user was added.
last_login (CharField): Last login date time of a user.
is_admin (CharField): If user is a admin or not.
is_active (CharField): If user is active or not.
is_staff (CharField): If user is staff or not.
is_superuser (CharField): If user is a superuser or not.
role (OneToOneField): One to one relationship with role table.
"""
name = models.CharField(max_length=80)
email = models.EmailField(max_length=255, unique=True)
mobile = models.CharField(
validators=[
RegexValidator(
regex=r"^\d{10,14}$",
message="Phone number must be entered in format: '+999999999'. Up to 14 digits allowed.",
)
],
max_length=15,
unique=True,
)
role = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True)
drivers = models.ManyToManyField(
"self", through="DispatcherDriver", symmetrical=False
)
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(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)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
updated_at = models.DateTimeField(auto_now=True, null=True, blank=True)
USERNAME_FIELD = "mobile"
REQUIRED_FIELDS = ["email", "name"]
objects = UserManager()
class Meta:
db_table = "users"
def __str__(self):
return self.name
# For checking permissions. to keep it simple all admin have ALL permissons
def has_perm(self, perm, obj=None):
return self.is_admin
# Does this user have permission to view this app? (ALWAYS YES FOR SIMPLICITY)
def has_module_perms(self, app_label):
return True
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
class CustomerInfo(models.Model):
customer = models.OneToOneField(
User, on_delete=models.CASCADE, primary_key=True, related_name="customer_info"
)
company_name = models.CharField(max_length=255)
class Meta:
db_table = "customer_info"
def __str__(self):
return self.company_name
CustomerInfo model has OneToOneField mentioned in the model. How can I access CustomerInfo of a User model using reverse relationship?
Suppose, you has User's instance user then you can fetch customer_info as
from django.core.exceptions import ObjectDoesNotExist
try:
customer_info = user.customer_info
except ObjectDoesNotExist:
print("There is no customer info here.")
Reference - https://docs.djangoproject.com/en/3.1/topics/db/examples/one_to_one/
Try:
myuser = User.objects.create(email="..", name="..", password="1223")
profile = CustomerInfo.objects.create(customer=myuser)
company_name = myuser.customer_info.company_name

Using ForeignKey of Django CustomUser giving attribute error

Not using Djnago Default user model. Have created a Custom user model named CustomUser
class CustomUser(AbstractBaseUser):
GENDER_CHOICE = (
('MALE', 'MALE'),
('FEMALE', 'FEMALE'),
)
BLOOD_GROUP_CHOICE = (
('A+', 'A+'),
('B+', 'B+'),
('O+', 'O+'),
('AB+', 'AB+'),
('A-', 'A-'),
('B-', 'B-'),
('O-', 'O-'),
('AB-', 'AB-'),
)
RELIGION_CHOICE = (
('ISLAM', 'ISLAM'),
('HINDU', 'HINDU'),
('CHRISTIANITY', 'CHRISTIANITY'),
('OTHER', 'OTHER'),
)
email = models.EmailField(max_length=60, unique=True, verbose_name='Email')
first_name = models.CharField(max_length=30, verbose_name='First Name')
last_name = models.CharField(max_length=30, verbose_name='Last Name')
gender = models.CharField(_("Employee Gender"),
max_length=6, choices=GENDER_CHOICE, null=True, blank=True)
blood_group = models.CharField(
_("Employee Blood Group"), max_length=3, choices=BLOOD_GROUP_CHOICE, null=True, blank=True)
birth_of_date = models.DateField(
_("Employee Birth Date"), auto_now=False, auto_now_add=False, null=True, blank=True)
#address = models.CharField(_("Employee Address"), max_length=500, null=True, blank=True)
address = models.CharField(_("Employee Address"), max_length=500, null=True, blank=True)
phone_number = PhoneNumberField(null=True, blank=True)
profile_pic = models.ImageField(_("Employee Profile Picture"), upload_to='profile_pic',
height_field=None, width_field=None, max_length=None, null=True, blank=True)
religion = models.CharField(
_("Employee Religion"), max_length=15, choices=RELIGION_CHOICE, null=True, blank=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ('first_name', 'last_name')
objects = CustomUserManager()
def __str__(self):
return self.email
def get_short_name(self):
return self.first_name
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return self.is_admin
class Meta:
verbose_name_plural = "Shunno ek Users"
Here is my CumstomUser models' CustomUsermanager
class CustomUserManager(BaseUserManager):
def create_user(self, email, first_name, last_name, password=None):
if not email:
raise ValueError('You must have an email')
email = email.lower()
first_name = first_name.title()
last_name = last_name.title()
user = self.model(
email = self.normalize_email(email),
first_name = first_name,
last_name = last_name
)
#user.password = password
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, first_name, last_name, password=None):
user = self.create_user(
email = email,
first_name = first_name,
last_name = last_name,
password = password
)
user.is_admin = True
user.is_staff = True
user.save(using=self._db)
return user
This is a model of saving users Quiz answers.
class UserAns(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='quiz_user')
quizcat = models.ForeignKey(Category, on_delete=models.CASCADE)
totalq = models.DecimalField(max_digits=5,decimal_places=2)
correcta = models.DecimalField(max_digits=5,decimal_places=2)
def __str__(self):
return self.User.first_name
It is view part where i want to save the data of user answer.
def quizpage(request, slug):
if request.method == 'POST':
# totalquestion
solve = 0
for question in range(1,cat.totalq+1):
entered_answer_questionpk = request.POST.get(str(question))
ans = entered_answer_questionpk[:1]
qpk = int(entered_answer_questionpk[1:])
actualans = Question.objects.get(pk=qpk).correct_answer
if ans == actualans:
solve = solve + 1
# print(user)
usersans = UserAns(totalq=cat.totalq, correcta=solve)
usersans.quizcat = cat
print(request.user)
usersans.user = request.user
usersans.save()
return render(request, 'quiz/quizpage.html',{'questions': questions })
after saving this value in the database, when I click the table name it gives this error:
Django Version: 3.1.3
Exception Type: AttributeError
Exception Value:
'UserAns' object has no attribute 'User'
I can't understand where is my problem.
Your string method is referencing self.User and not self.user.
def __str__(self):
return self.user.first_name
Previous answer:
You should also look through your view that's rendering the page and protect any parts that access userans.user via if hasattr(userans, 'user'): or if userans.user_id:.
Another thing you can do is clean up your data. Your post view looks to be about right. But that page is failing because you have instances that still have the user property with a value of None.Open up a shell manage.py shell, import your UserAns model and see if you have any instances without a user. If you do, determine which user(s) they should map to or delete them.
UserAns.objects.filter(user__isnull=True)

Forms - Foreign Key - ModelChoiceField - NOT SAVING

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='')

Multiple type user's authority is messy when change user profile with UpdateView - Django

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')