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
Related
I want to get username from custom users model
My Custom Users model:
class Account(AbstractBaseUser, PermissionsMixin):
nickname = models.CharField(max_length=150, unique=True)
name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
phone = models.CharField(max_length=50, unique=True)
date_of_birth = models.DateField(blank=True, null=True)
picture = models.ImageField(blank=True, null=True)
is_staff = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
last_login = models.DateTimeField(null=True)
admin_of_company = models.ForeignKey('companies.company', on_delete=models.CASCADE, default=None, blank=True,
null=True)
objects = AccountManager()
USERNAME_FIELD = 'nickname'
REQUIRED_FIELDS = ['name', 'last_name', 'phone']
def get_full_name(self):
return self.name, self.last_name
def get_short_name(self):
return self.name.split()[0]
and products model:
class products(models.Model):
name = models.CharField(max_length=150)
about = models.TextField()
price = models.IntegerField()
picture = models.ImageField(default=None)
admin = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
in products.admin I want to set default logged in user
but I don't know how to get this data from custom users model
If you would like to get a current account in your view use this
current_user_id = self.request.user.id
current_account = Account.objects.get(pk=current_user_id)
current_account_nickname = current_account.nickname
Your model Account doesn't have "username" field.
You have to add it if you would like to use "username".
class Account(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=150, unique=True)
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',
]
I’m really new in python and a need your help please!
I’m trying to display a list of “anomalie” objects only showing the elements that corresponds to the “User” according to the “Aisles” assigned to him (in a many-to-many relationship)
So the model.py is as follows:
class Aisle(models.Model):
aisle_code = models.IntegerField(null=False, blank=False)
aisle_name = models.CharField(
max_length=60, null=False, blank=False)
def __str__(self):
return self.aisle_name
def __nonzero__(self):
return bool(self.aisle_name or self.aisle_name)
class Account (AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, 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)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
phone_regex = RegexValidator(
regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
phone_number = models.CharField(
validators=[phone_regex], max_length=17, blank=True)
role = models.CharField(max_length=50)
store = models.CharField(max_length=50)
aisle = models.ManyToManyField(Aisle)
user_identification = models.CharField(max_length=30, unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'first_name', 'last_name',
'phone_number', 'role', 'store', 'aisle', 'user_identification']
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
#property
def staff(self):
return self.is_staff
#property
def active(self):
return self.is_active
class Anomalie (models.Model):
ANOMALIE = (
("Etiquette absente", "Etiquette absente"),
("Etiquette decalee", "Etiquette decalee"),
("Etiquette inconnue", "Etiquette inconnue"),
)
ANOMALIE_STATE = (
("traité", "traité"),
("mise à jour", "mise à jour"),
("signalé", "signalé"),
)
type = models.CharField(
max_length=200, choices=ANOMALIE, null=False)
date_report = models.DateTimeField(null=False, blank=False)
localization = models.TextField(max_length=30, null=False, blank=False)
state = models.CharField(
max_length=200, choices=ANOMALIE_STATE, null=False)
aisle = models.ForeignKey(Aisle, null=True, on_delete=models.SET_NULL)
product = models.ForeignKey(
Product, null=True, on_delete=models.SET_NULL)
def datepublished(self):
return self.date_report.strftime('%B %d %Y')
def __str__(self):
return self.type
When I’m trying to get the objects query set in the view.py, an error occurs, so the question is how could I get the query set objects in a many-to-many relationship?
anomalies = request.user.aisle.get_anomalie_queryset.all()
There is my view.py
#login_required(login_url='login')
def home_screen_view(request):
context = {}
user_aisles = request.user.aisle.all()
anomalies = request.user.aisle.get_anomalie_queryset.all()
list_anomalies_user = []
for aisle in user_aisles:
print('aisle in user aisles list', aisle)
user_aisle_type = type(aisle)
print(user_aisle_type)
for anomalie in anomalies:
print(anomalie.aisle)
if(aisle == anomalie.aisle):
print("son iguales")
tuple(list_anomalies_user)
list_anomalies_user.append(anomalie)
# is type list
type_list = type(list_anomalies_user)
print("tipo de dato de la lista anomalia user", type_list)
type_anomalies = type(anomalies)
print("tipo de dato de anomaliesr", type_anomalies)
print("list_anomalies_user", list_anomalies_user)
print('user aisles', user_aisles)
print('anomalies', anomalies)
context = {'anomalies': anomalies,
'list_anomalies_user': list_anomalies_user}
return render(request, "personal/home.html", context)
I will really thank you for your help!
I am using a custom User model. And I have another Customer model. I want the user field will only show the staff user no other type of user in the field will show in the registration form. In my case, it is showing all types of users whether it is staff or customer or a service user.
Models.py
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=254, unique=True)
name = models.CharField(max_length=254, null=True)
email = models.EmailField(max_length=254, null=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_Customer = models.BooleanField(default=False)
is_Service_Provider = models.BooleanField(default=False)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'username'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % self.pk
def get_username(self):
return self.username
class Customer(models.Model):
user = models.OneToOneField('accounts.User', on_delete=models.SET_NULL, null=True)
email = models.EmailField(max_length=254, null=False)
date_Of_Birth = models.DateField(null=False)
country = models.ForeignKey('accounts.Country', null=True, on_delete=models.SET_NULL, related_name='Country')
state = models.ForeignKey('accounts.State', null=True, on_delete=models.SET_NULL, related_name='State')
city = models.ForeignKey('accounts.City', null=True, on_delete=models.SET_NULL, related_name='city')
address = models.CharField(max_length=254, null=False)
refernce_by_person_name = models.CharField(max_length=254, null=True)
refernce_by_person_contact_no = models.IntegerField(null=True)
phone_no = models.IntegerField(null=False)
alternate_no = models.IntegerField(null=False)
hobbies = models.CharField(max_length=254)
def __str__(self):
return self.user.username
views.py
def form(request):
forms = CustomerRegistrationForm()
if request.method == "POST":
forms = CustomerRegistrationForm(request.POST)
if forms.is_valid():
forms.save()
return redirect('/customer/show')
context = {
'forms' : forms,
}
return render(request,'customer/form.html', context)
forms.py
class CustomerRegistrationForm(forms.ModelForm):
class Meta:
model = Customer
fields = '__all__'
You can filter the staff users in the form like this.
class CustomerRegistrationForm(forms.ModelForm):
user = forms.ModelChoiceField(queryset=User.objects.filter(is_staff=True))
class Meta:
model = Customer
fields = ['user','email','date_of_birth',...]
I ran python manage.py migrate accounts zero then i faced an error,
I checked my models multiple times it seems everything is ok but...!?
This is the error:
django.db.utils.IntegrityError: (1062, "Duplicate entry '1' for key 'accounts_post_user_id_ecf3e197_uniq'")
User model:
class User(AbstractBaseUser):
id = models.BigAutoField(primary_key=True)
username = models.CharField(max_length=30, unique=True)
email = models.EmailField(max_length=191, unique=True)
email_verified = models.BooleanField(default=False)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_verified = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
objects = UserManager()
USERNAME_FIELD = 'username'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['email', 'first_name', 'last_name']
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return self.is_admin
Post model:
class Post(models.Model):
id = models.BigAutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
channel = models.ForeignKey(Channel, on_delete=models.CASCADE, null=True, blank=True)
hashed_id = models.CharField(max_length=191)
text = models.TextField(max_length=270)
visits = models.IntegerField(default=0)
comment_status = models.BooleanField(default=True)
edited = models.BooleanField(default=False)
signature = models.CharField(max_length=191)
deleted_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
There was 1 user with 2 posts.
I added unique=False to ForeignKey fields and it solved the problem.
I hope if this error occurs in your app this answer gives you a hand.