use django-guardian with Custom User - django

I use custom user And i want to django-guardian to handle the permissions and groups. How i can do that
my user:
class ProfileUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
username = models.CharField(max_length=255,unique=True)
first_name=models.CharField(max_length=255)
last_name= models.CharField(max_length=255)
departement= models.CharField(max_length=255)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []

Just add a OneToOne field in the ProfileUser model that points to an actual user or use any other method included in the django documentation about extending the user model.

Related

Django 4.0 - Trying to run a query based on result from another query

guys!
Here's what I'm trying to do:
I have a User model, a LinkedOrganization model, an Organization model that looks like this:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(db_index=True, unique=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
mobile = models.CharField(max_length=12)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_superuser = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'mobile']
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
# Organization fields
class Organization(models.Model):
organization_name = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.organization_name
class LinkedOrganization(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='linked_user')
organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name='linked_organization')
is_manager = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
class Meta:
unique_together = (
("user", "organization")
)
In my API-view I'm trying to return all the users that are linked to an organization that the requester is a manager of.
Now, one requester can be a manager of 1 or more organizations, and I need to get all the users linked to those organizations. Meaning I need it to be sort of 'is member of organization A' OR 'is member of organization B', and iterate through all the organizations. Is it possible to do this with a Queryset in Django?
I realized when I wrote this that I could just get the organizations and use ReverseObjectManager to get the users of the organizations and iterate through those and make the dictionaries I need in Python, but if getting a query and use the result in a queryset is a function of Django that would be easier.
You may benefit from a slightly different database schema, not just for this query but in general. Consider the following:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(db_index=True, unique=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
mobile = models.CharField(max_length=12)
organization = models.ForeignKey('Organization', on_delete=models.CASCADE, related_name='user_organization')
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_superuser = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'mobile']
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
# Organization fields
class Organization(models.Model):
organization_name = models.CharField(max_length=50, unique=True)
manager = models.ForeignKey(User, etc...)
def __str__(self):
return self.organization_name
In this scenario, every user has an organization, and every organization has a manager. Simple. Also note that I referenced the 'Organization' in the foreign key field as a string, since it is declared above where the Organization model is defined. With that, you can query like so:
managed_users = User.objects.filter(user_organization__manager=request.user)
A common practice is to create a profile model for the user, where additional fields like their organization, contact info, etc can be added. In that case you'd have something like this:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
organization = models.ForeignKey(Organization, etc...)

modelManager get_by_natural key method change the USERNAME_FIELD affecting my authentication?

I have a custom User model that inherits from AbstractBaseUser which defines the username_field = email so that users will login using emails.
class User(AbstractBaseUser):
email = models.EmailField(verbose_name="Email", unique=True)
username = models.CharField(max_length=100, unique=True)
last_name = models.CharField(max_length=100, blank=True, null=True)
first_name = models.CharField(max_length=100, blank=True, null=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_site_administrator = models.BooleanField(default=False)
is_developer = models.BooleanField(default=False)
is_project_manager = models.BooleanField(default=False)
last_login = models.DateTimeField(verbose_name="Last Login", auto_now=True)
create_on = models.DateTimeField(verbose_name="Date Created", default=timezone.now)
# So that we will be working primarily with email and not username
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
objects = UserManager()
As the objects = UserManager() and this one contains a get_by_natural_key method as follows:
def get_by_natural_key(self, username):
return self.get(username=username)
Now rather using the email to login it uses the username to login. Note that the userManager inherits from BaseUserManager like this class UserManager(BaseUserManager):
Can somebody explain to me what is going on here.
Is the problem coming from the inheritance or the get_by_natural_key() itself ?

how to implement two user types (seller and customer or buyer) using django allauth like fiverr?

I am working on a web e-commerce project where there will be two types of user (seller, customer). I have been wondering how to implement the logic like fiverr seller and buyer. I have created a user account with two flags yet (is_seller, is_customer).
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
name = models.CharField(max_length=254, blank=True)
customer = models.ForeignKey('Customer', on_delete=models.CASCADE)
is_seller = models.BooleanField(default=False)
is_customer = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
I want 2 users (seller and customer). A seller can request for a customer account as well (so same email will be used for login and signup) and vice versa.
what will be the best approach to this kind of scenario?
If they all share the same data fields then this might be the simplest way to do it. I'd only recommend multiple user models if there'll be different data captured. In that case, you could extend the User model.

Querying Parent from the foreign key django

I have the following models :
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=32)
last_name = models.CharField(max_length=32)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email' # unique identifier, changed to email (default was username)
REQUIRED_FIELDS = ['first_name', 'last_name']
objects = CustomUserManager() # custom manager for interacting with database
def __str__(self):
return self.email
class Refer(models.Model) :
referred_by = models.ForeignKey(CustomUser, on_delete=models.CASCADE, default='admin', related_name='referred_by')
referrals = models.ManyToManyField(CustomUser, related_name='referrals', blank=True)
unique_ref_id = models.CharField(max_length=8, blank=True, default=generate())
def __str__(self) :
return f'Referred By: {self.referred_by}'
I want to implement referral system using this, I have unique_for_id field (example 'exbvagtl'), how can i create new referral under that user?
Something like : Refer.objects.create(referred_by= CustomUser.objects.get(Refer__unique_ref_id='exbvagtl'))
Better model designs, resources and improvements are heavily welcomed!
I think you are overcomplicating things. By making a Refer object that has a ForeignKey to CustomUser, this means that each CustomUser can have zero, one or more Refer objects. While that is not impossible to manage, it makes it harder, since now your views will need to make sure you are working with the correct Refer object, or have to "concatenate" these. Furthermore it means that a CustomUser can have multiple unique_ref_ids.
The question is why we need such object in the first place. You can simply construct a unique_ref_id on the CustomUser object, and add a ForeignKey to 'self' that specifies what the referring person was:
class CustomUser(PermissionsMixin, AbstractBaseUser):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=32)
last_name = models.CharField(max_length=32)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now_add=True)
unique_ref_id = models.CharField(max_length=8, blank=True, default=generate)
referred_by = models.ForeignKey(
'self',
related_name='referrals',
null=True,
default=None,
on_delete=models.SET_NULL
)
USERNAME_FIELD = 'email' # unique identifier, changed to email (default was username)
REQUIRED_FIELDS = ['first_name', 'last_name']
objects = CustomUserManager() # custom manager for interacting with database
def __str__(self):
return self.email
Here we thus can add a user that was referred to by another user with:
CustomUser.objects.create(referred_by_id=id_of_referred_user)
If later the referred_by user is removed, then it will be set to NULL.
You can also query the users that have been referred by a user with:
myuser.referrals.all()
The problem is coming from your design of the referral system. Usually, in a referral system, one user has one referral_id. But your design suggests that one user can have multiple referral_ids.
I will suggest you move the unique_ref_id to the CustomUser model. That way you can do something like this:
Refer.objects.create(referred_by=CustomUser.objects.get(unique_ref_id="exbvagtl"))
2nd suggestion: put everything in one table
You will notice that the person referring another person is also a person, so it's basically a reference to self. In that regards you can have your CustomUser model look as follows:
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=32)
last_name = models.CharField(max_length=32)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
referred_by = models.ForeignKey(self, on_delete=models.SET_NULL, blank=True, null=True)
unique_ref_id = models.CharField(max_length=8, blank=True, default=generate())
USERNAME_FIELD = 'email' # unique identifier, changed to email (default was username)
REQUIRED_FIELDS = ['first_name', 'last_name']
objects = CustomUserManager() # custom manager for interacting with database
def __str__(self):
return self.email
Base on that, you can do things like this:
Create a new user:
sponsor = CustomUser.objects.get(unique_ref_id="exbvagtl")
user = CustomUser(email=email, first_name=first_name, last_name=last_name,referred_by=sponsor)
user.save()
Get the list of a user's referrals:
sponsor = CustomUser.objects.get(unique_ref_id="exbvagtl")
referrals = CustomUser.objects.filter(referred_by=sponsor)
Hope this helps, if you have any doubts, don't hesitate to ask below.

Multiple user Login where multiple user can login and get redirected to respective pages

I have four types of user like buyer seller organizer and staff. So i would like to know how to implement multiple type login in django
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class Seller(AbstractBaseUser):
"""
Custom user class.
"""
email = models.EmailField('email address', unique=True, db_index=True)
joined = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_seller = models.BooleanField(default=False)
class Buyer(AbstractBaseUser):
"""
Custom user class.
"""
email = models.EmailField('email address', unique=True, db_index=True)
joined = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_buyer = models.BooleanField(default=False)
class Staff(AbstractBaseUser):
"""
Custom user class.
"""
email = models.EmailField('email address', unique=True, db_index=True)
joined = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
class Organizer(AbstractBaseUser):
"""
Custom user class.
"""
email = models.EmailField('email address', unique=True, db_index=True)
joined = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
is_organizer = models.BooleanField(default=False)