add permission to model - python

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().

Related

SQL Django Null Constraint Error - cannot resolve?

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']
# ...

RelatedObjectDoesNotExist at / Accounts has no customer

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)

How to query related models in django models.py

I have a user model which looks like this:
class User(AbstractUser):
first_name = models.CharField(max_length=70)
last_name = models.CharField(max_length=70)
middle_name = models.CharField(max_length=70, blank=True)
email = models.EmailField(
max_length=254,
unique=True,
verbose_name='Email Address',
blank=True
)
is_student = models.BooleanField(default=False, verbose_name='Student')
is_superuser = models.BooleanField(default=False, verbose_name='Administrator')
is_teacher = models.BooleanField(default=False, verbose_name='Teacher')
is_staff = models.BooleanField(default=False, verbose_name='Staff')
is_registrar = models.BooleanField(default=False, verbose_name='Registrar')
and in my StudentPorile model I have a field called class_advisor which is related to User model and I need to get the users with is_teacher field is True. Now, how do i filter class_advisor field to return Users only with is_teacher=True?
here's my StudentProfile model:
class StudentProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
lrn = models.CharField(max_length=20)
landline_number = models.CharField(max_length=11, null=True, blank=True)
mobile_number = models.CharField(max_length=11, null=True, blank=True)
address = models.TextField(max_length=300, blank=True)
mothers_name = models.CharField(max_length=50)
fathers_name = models.CharField(max_length=50)
contact_person_name = models.CharField(max_length=50)
contact_person_number = models.CharField(
max_length=12, verbose_name='Phone number of Contact Person')
# class_advisor = IM STUCK HERE
year_level = models.OneToOneField(Year_Level, on_delete=models.SET_NULL, null=True)
section = models.OneToOneField(Section, on_delete=models.SET_NULL, null=True)
This should return you a queryset of all the Users who have their is_teacher attribute set to True
User.objects.filter(is_teacher=True)
views.py
class MyView(View):
def get(self, request):
filtered_users = User.objects.filter(is_teacher=True)
return render(request, 'home.html', context={'users': filtered_users})
template.html
{% for user in users %}
{{user}}
{% endfor %}

django-rest-auth "userprofile with this email address already exists." in login

I'm using django rest auth for auth in my rest api. I use custom user model with no username field. So, I've to use custom login serializer. But when I log in, django rest auth says "userprofile with this email address already exists.". How to solve this problem?
my settings:
REST_USE_JWT = True
REST_AUTH_SERIALIZERS = {
'LOGIN_SERIALIZER': 'accounts.api.serializers.RestAuthLoginSerializer',
'REGISTER_SERIALIZER': 'accounts.api.serializers.RestAuthRegisterSerializer',
}
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_USER_MODEL_USERNAME_FIELD = 'email'
ACCOUNT_USERNAME_REQUIRED = False
serializers.py
from rest_framework import serializers
from accounts.models import UserProfile
class RestAuthLoginSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ('email', 'password')
class RestAuthRegisterSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ('email', 'password', 'first_name', 'last_name', 'business_name', 'is_business_account')
models.py
class UserProfile(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True, null=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True, null=True)
avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)
# business profile related data
business_name = models.CharField(_('business name'), max_length=30, blank=True, null=True)
business_phone = models.CharField(_('business phone'), max_length=20, blank=True, null=True)
is_business_account = models.BooleanField(verbose_name=_("is business account"), default=False)
date_joined = models.DateTimeField(_('date joined'), auto_now_add=True)
is_active = models.BooleanField(_('active'), default=True)
is_admin = models.BooleanField(_('staff status'), default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
I found the problem and fixed it myself. I just had to add
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend"
)
to settings.py file.

Auto add user firstname in author field in django with custom User model

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

Categories

Resources