What am I doing wrong?
Django Models:
USER MODEL
class User(AbstractUser):
# DEFINE MODEL FIELDS
related_person = models.OneToOneField(Person, on_delete=models.CASCADE, default='')
user_id = models.BigAutoField(verbose_name='User ID', primary_key=True, serialize=False, auto_created=True)
email = models.EmailField(verbose_name='Email', max_length=80, blank=False, unique=True, null=False, default='')
is_verified = models.BooleanField(verbose_name='Email Verified', blank=False, default=False)
date_joined = models.DateField(verbose_name='date joined', auto_now_add=True, null=True)
last_login = models.DateField(verbose_name='last login', auto_now=True, null=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
first_name = None
last_name = None
username = None
# IMPORT MODEL MANAGER CLASS
objects = UserManager()
# SET LOGIN FIELD
USERNAME_FIELD = 'email'
# SET REQUIRED FIELDS
REQUIRED_FIELDS = ['is_verified']
PERSON MODEL
class Person(models.Model):
class Titles(models.TextChoices):
MR = 'Mr', _('Mr')
MRS = 'Mrs', _('Mrs')
MISS = 'Miss', _('Miss')
MS = 'Ms', _('Ms')
DR = 'Dr', _('Dr')
related_entity = models.OneToOneField(Entity, on_delete=models.CASCADE)
person_id = models.BigAutoField(verbose_name='Person ID', primary_key=True, serialize=False, auto_created=True)
first_name = models.CharField(verbose_name='First Name', max_length=50, blank=False, null=False)
last_name = models.CharField(verbose_name='Last Name', max_length=50, blank=False, null=False)
title = models.CharField(verbose_name='Title', max_length=4, choices=Titles.choices, blank=True, null=False, default='')
alias = models.CharField(verbose_name='Alias', max_length=150, blank=True, null=False)
ENTITY MODEL
class Entity(models.Model):
class EntityTypes(models.TextChoices):
PERSON = 'Person', _('Person')
COMPANY = 'Company', _('Company')
entity_type = models.CharField(
verbose_name='Legal Entity Type',
max_length=7,
choices=EntityTypes.choices,
default=EntityTypes.PERSON,
blank=False,
null=False)
I have a Sign Up form that saves a person's email to the User Model, and password to the User Model, after checking the email doesn't already exist, and passwords (when entered twice), match. but then I get this error when I save the form:
null value in column "related_person_id" of relation "customauth_user" violates not-null constraint
DETAIL: Failing row contains (1, pbkdf2_sha256$320000$Ipsu5kX2Opd2a1j9996ReS$uPR4GCbSxS7+9+0KIAaE..., sachin#cantab.net, f, 2022-02-28, 2022-02-28, t, f, f, f, null).
Any ideas?
The overall idea behind the models was to allow a someone to signup with an email and password, through the User model. Then once they've logged in, they can enter their firstname, lastname, title, alias, etc, in the Person model.
Your User-Model does not allow null to be set as value for the column related_person (Django's ORM transpiles this to related_person_id in SQL)
By default this causes SQL to put a Null-Constraint on that column.
However you can prevent Django from implementing such a Constraint, by simply parsing null = True as additional argument to the affected column of your Model.
Thus you can simply change your Models to:
class User(AbstractUser):
# DEFINE MODEL FIELDS
related_person = models.OneToOneField(Person, on_delete=models.CASCADE, default='', null=True) # allowing null-values
user_id = models.BigAutoField(verbose_name='User ID', primary_key=True, serialize=False, auto_created=True)
email = models.EmailField(verbose_name='Email', max_length=80, blank=False, unique=True, null=False, default='')
is_verified = models.BooleanField(verbose_name='Email Verified', blank=False, default=False)
date_joined = models.DateField(verbose_name='date joined', auto_now_add=True, null=True)
last_login = models.DateField(verbose_name='last login', auto_now=True, null=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
first_name = None
last_name = None
username = None
# IMPORT MODEL MANAGER CLASS
objects = UserManager()
# SET LOGIN FIELD
USERNAME_FIELD = 'email'
# SET REQUIRED FIELDS
REQUIRED_FIELDS = ['is_verified']
# ...
Related
So I have a user model that has a foreign key relation with class/room, I want a user to be able to press one button and all the users/students would be equally distributed throughout the class/room foreign key based on fields from the model like age, height and other fields.
so if there are 4 students 2 with age 14 and 2 with age 15 and there are two classes, the function should put one 14-year-old and one 15-year-old in 1 class and the same in the other class as well, just iterate through the users and distribute them by the selected field values equally, any resource or code snippet would be highly appreciated.
user model if needed
class User(AbstractBaseUser, PermissionsMixin):
class SEX(models.TextChoices):
MALE = "MALE", "Male"
FEMALE = "FEMALE", "Female"
id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False, unique=True)
sex = models.CharField(
_("Sex Type"), max_length=50, choices=SEX.choices, default=None, blank=True, null=True)
email = models.EmailField(
_("Email"), max_length=254, unique=True, default=None, blank=True, null=True)
student_id = models.CharField(
_("student id"), unique=True, max_length=10, blank=True, null=True)
firstname = models.CharField(max_length=250, blank=False, null=True)
middlename = models.CharField(max_length=250, blank=False, null=True)
lastname = models.CharField(max_length=250, blank=False, null=True)
grade = models.ForeignKey(Grade, verbose_name=_(
"grade"), on_delete=models.SET_NULL, blank=True, null=True)
room = models.ForeignKey(Class, verbose_name=_(
"class"), related_name="student_room", on_delete=models.SET_NULL, blank=True, null=True) // class model forignkey
age = IntegerRangeField(min_value=1, max_value=99,
default=25, blank=True, null=True)
image = models.ImageField(
_("photo"), upload_to='user/Users/profile_pic', max_length=None, blank=False, null=True)
joined_date = models.DateTimeField(
_("created at"), auto_now=False, auto_now_add=True)
has_rated = models.BooleanField(_("Has rated the app"), default=False)
...
class Meta:
verbose_name = _("User")
verbose_name_plural = _("Users")
ordering = ('-joined_date',)
objects = CustomAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['firstname', 'lastname']
def __str__(self):
return self.firstname
I have given a code snippet for you to find a solution.It might not be the efficient solution. But you shall have gist.
def assign_class(request, *args, **kwargs):
age14_users = User.objects.filter(age=14).order_by('-joined_date')
age14_users_pk_list=list(age14_users.values_list('pk', flat=True))
age15_users = User.objects.filter(age=15).order_by('-joined_date')
age15_users_pk_list=list(age15_users.values_list('pk', flat=True))
age14_users_count = len(age14_users_pk_list)
age15_users_count = len(age15_users_pk_list)
classes= Class.objects.all()
class_count = classes.count()
class_pk_list=list(classes.values_list('pk', flat=True))
slice = age14_users_count//class_count
sliced_users_list_age14=[age14_users_pk_list[i:i+slice] for i in range(0, len(age14_users_pk_list), slice)]
#output eg. [[1,2,3],[4,5,6],[7,8]]
#User will be distributed to rooms rationally
'''
if we loop through sliced user clusters.. we can assign
each cluster to room rationally
'''
new_class_pk_list = class_pk_list.copy()
for lst in sliced_users_list_age14:
for user_pk in lst:
user = User.objects.get(pk=user_pk)
user.room_id =new_class_pk_list[0]
user.save()
del new_class_pk_list[0] #delete the class after assigning
#from copied list
'''
Now you can distribute the other cluster of group (eg. age15_users)
like above
'''
Here i have two models Keys and Users i am creating POST API so i got encounter with this Error .
UserModel.py:
class Users(AbstractBaseUser):
vendor_name = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None)
key_value = models.ForeignKey(KeyTable, on_delete=models.CASCADE, default=None, null=True)
username = models.CharField(max_length=100, verbose_name="username", unique=True)
password = models.CharField(max_length=100)
hardware_id = models.CharField(max_length=150, null=True)
created_by = models.DateField(verbose_name="created_by", auto_now_add=True)
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ['password', 'hardware_id']
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_role_vendor = models.BooleanField(default=False)
is_role_customer = models.BooleanField(default=True)
def __str__(self):
return self.username
objects = UserManager()
KeyModel.py:
class KeyTable(models.Model):
key_id = models.IntegerField(unique=True, auto_created=True)
key_value = models.CharField(max_length=100)
issue_date = models.DateField(max_length=100)
expiry_date = models.DateField()
status = models.CharField(max_length=50)
license_tenure = models.IntegerField()
def __str__(self):
return self.key_value
KeySerializer:
class KeySerializer(serializers.ModelSerializer):
class Meta:
model: Keys
fields = ['key_id', 'key_value', 'issue_date', 'expiry_date', 'status', 'license_tenure']
Error Encounters:
django.db.utils.IntegrityError: NOT NULL constraint failed: app_users.key_value_id
you can set null=True and blank=True in the model field which is causing you an error
or you can delete the app and create it again with the same code this trick can also work.
But if you do not find solution then you can find several solutions here.
The problem arises while creating new users. It says related object does not exist.
accounts model
class Accounts(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
date_created = models.DateTimeField(
verbose_name='date_joined', auto_now_add=True)
last_login = models.DateTimeField(
verbose_name='last_login', auto_now_add=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=50)
last_name = models.CharField(max_length=50)
# setting username as a key to login. Note: email can also be used in it
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['first_name', 'last_name', 'email']
store model
class Customer(models.Model):
username = models.OneToOneField(
Accounts, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=100, null=True)
email = models.CharField(max_length=100, null=True)
def __str__(self):
return self.name
in your views as the error says you tried
customer = request.user.customer
while you have nothing namer customer a all in your Customer class but a username
so either :
change your query in the views to :
customer = request.user.username
or
change the username in your class to customer :
customer = models.OneToOneField( Accounts, on_delete=models.CASCADE, null=True,
blank=True)
I have two models, abstract user and admin, linked onetoonefield. I want to add permissions for admin. I registered in meta permissions, but they are not saved or created in the database. What do I need to do? When I call
admin.has_perm ('MoveOnApp.register_partner')
I get the error
'Admin' object has no attribute 'has_perm'
class AbstractUser(AbstractBaseUser, PermissionsMixin):
"""Создал абстрактоного юзера от которого будут унаследованны остальные юзеры"""
phone_number = models.CharField(
_('phone number'),
max_length=14,
unique=True,
help_text='Enter your phone number',
)
email = models.EmailField(_('email address'), blank=True, unique=True)
created = models.DateTimeField(_('date joined'), default=datetime.datetime.now())
USERNAME_FIELD = 'phone_number'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['email']
objects = BaseManager()
is_superuser = None
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
class Admin(models.Model):
"""Создаю модель администратора, наследованную от AbstractUser"""
user = models.OneToOneField(AbstractUser, on_delete=models.CASCADE, primary_key=True)
company_name = models.CharField(
_('company name'),
max_length=150,
)
logo_url = models.ImageField(
upload_to='img/logo'
)
first_name = models.CharField(
_('first name'),
max_length=50
)
last_name = models.CharField(
_('last name'),
max_length=50,
)
# Флажок, такие права доступа рекомендует делать документация. Есть еще варианты но этот мне кажется самым удобным
is_admin = models.BooleanField(
_('admin status'),
default=True
)
objects = BaseManager()
class Meta:
permissions = (
("register_partner", "Can register partner"),
)
Your Admin model is a basic model that has a user, but is not an user itself, to access its user-related properties you need to access the user attribute, like admin.user.has_perm().
I created Custom User model in django using below code
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
username = models.CharField(_("Username"), max_length=50, unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', ]
objects = CustomUserManager()
def __str__(self):
return self.email
And I also created another model for user profiles like below.
class UserProfile(models.Model):
user = models.OneToOneField(User, verbose_name=_("User"), on_delete=models.CASCADE)
first_name = models.CharField(_("First name"), max_length=50)
middle_name = models.CharField(_("Middle name"), max_length=50, blank=True, null=True)
last_name = models.CharField(_("Last name"), max_length=50)
dob = models.DateField(_("D.O.B"), auto_now=False, auto_now_add=False, blank=False, null=False)
profile_image = models.ImageField(_("Profile picture"), upload_to='user/profile/', blank=True)
webiste_link = models.URLField(_("Websites"), max_length=200, null=True, blank=True)
At last I created another model for Category like below.
class Category(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_(
"Author"), on_delete=models.CASCADE, related_name='blog_category')
title = models.CharField(_("Title"), max_length=50)
I want to auto save logged in user full name instead of user email address. By the way i used below code to auto save logged in user. It works but It only save user email address. But I want user full name instead of email or username.
obj.author = request.user
super().save_model(request, obj, form, change)
You could define a method in the UserProfile model to build this fullname, as you may need it in another function :
class UserProfile(models.Model):
user = models.OneToOneField(User, verbose_name=_("User"), on_delete=models.CASCADE)
[...]
def get_fullname(self):
return ' '.join([name for name in [
self.first_name,
self.middle_name,
self.last_name
] if name])
So you keep this way to save the user foreignkey in a Category:
obj.author = request.user
And later, to call the fullname on a category instance you can use :
# cat = Category.objects.first()
cat.author.userprofile.get_fullname()
You can add a filed called full_name in UserProfile model
Class UserProfile(models.Model):
user = models.OneToOneField(User, verbose_name=_("User"), on_delete=models.CASCADE)
first_name = models.CharField(_("First name"), max_length=50)
full_name = mdoels.CharField(_("Full name"),max_length=100)
middle_name = models.CharField(_("Middle name"), max_length=50, blank=True, null=True)
last_name = models.CharField(_("Last name"), max_length=50)
dob = models.DateField(_("D.O.B"), auto_now=False, auto_now_add=False, blank=False, null=False)
profile_image = models.ImageField(_("Profile picture"), upload_to='user/profile/', blank=True)
webiste_link = models.URLField(_("Websites"), max_length=200, null=True, blank=True)
def save(self,*args,**kwargs):
if not self.full_name:
self.full_name = self.first_name + " " + self.middle_name + " " + self.last_name
super().save(*args, **kwargs)
And then using author you can call the users full_name