I have following users in my Django applications:
1. Normal user (UUID, email, name, address, password)
2. Remote application (UUID, name, generated random secret)
3. (other type of remote application)
The authentication for the Normal user would be with webpage email + password
The authentication for the Remote application would be with UUID + random secret with JSON to ask for the temporary token
I do not know how to handle this in Django. I wanted to create AuthBaseUser from AbstractBaseUser like:
class AuthBaseUser(AbstractBaseUser, PermissionsMixin):
pk = models.UUIDField(primary_key=True, unique=True, default=uuid.uuid4, editable=False,)
name = models.CharField(_('name'), max_length=128, blank=False)
typ = models.CharField(max_length=16, choices=USER_TYPES, default='normaluser',)
date_joined = models.DateTimeField(_('date joined'), auto_now_add=True, default=timezone.now)
last_login = models.DateTimeField(_('last login'), auto_now_add=True)
is_active = models.BooleanField(_('active'), default=True)
Then I wanted to create a RemoteAppUser and NormalUser with 1:1 mapping like this:
class NormalUser(AuthBaseUser):
user = models.OneToOneField(AuthBaseUser, on_delete=models.CASCADE)
email = models.EmailField(_('email address'), unique=True)
is_superuser = models.BooleanField(_('superuser'), default=True)
#password = #not decided yet what to add here; for remote app we will have 256b of SHA256's random generated value
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = AuthBaseUser.REQUIRED_FIELDS.append(['email', 'password', ])
objects = NormalUserManager()
def __init__(self, *args, **kwargs):
super(AuthBaseUser, self).__init__(*args, **kwargs)
def __str__(self):
return self.get_username()
def get_full_name(self):
return self.get_username()
def get_short_name(self):
return self.get_username()
Of course, I have to add the default auth user:
AUTH_USER_MODEL = 'myauth.AuthBaseUser'
Is there any recommended way to handle such different users?
Note that for example I would like store the RemoteApp's secret as SHA256, but I do not need to run the permutations several times with seed etc.
may be just create something like this:
class User(AbstractBaseUser, PermissionsMixin):
name = models.CharField(_('name'), max_length=128, blank=False)
is_normal = models.BooleanField(default=False)
is_other = models.BooleanField(default=False)
and one class for two types of the authentications, and just check is_normal user or is_other user
UPDATE:
try like this:
class EnterpriseEntry(models.Model):
user = models.ForeignKey('User', null=False, blank=False, verbose_name=u'Пользователь',
related_name='enterprise_entries')
position = models.CharField(
max_length=100, default="", blank=True, verbose_name=u'Позиция в компании')
ADMIN_ENTERPRISE = 0
USER = 1
ENTREPRENEUR = 2
UNKNOWN = 3
MODERATOR = 4
PROFILE_TYPES = (
(ADMIN_ENTERPRISE, u'Руководитель юридического лица'),
(USER, u'Пользователь приглашенный в предприятие'),
(ENTREPRENEUR, u'Индивидуальный предприниматель'),
(MODERATOR, u'Модератор компании'),
(UNKNOWN, u'Не известно'),
)
Related
I have a problem in my code,I'm Trying to querying to my course model, I have a many to may field of course in user model,now I need to query to course model that course title or id is equal to user's courses
My course model is:
class Courses(models.Model):
title = models.CharField(max_length=100, null=False, blank=False)
description = models.TextField(null=False, blank=False)
active = models.BooleanField(default=False)
default_course = models.BooleanField(default=False)
My user model in another app is:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True, db_index=True)
courses = models.ManyToManyField('academy.Courses', related_name='user_courses',
blank=True)
is_verified = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_author = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_adviser = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
auth_provider = models.CharField(
max_length=255, blank=False,
null=False, default=AUTH_PROVIDERS.get('email'))
I have to say my user model and course model are in different app
This is my view:
class CoursesListView(mixins.ListModelMixin, viewsets.GenericViewSet):
serializer_class = UserSerializer
def get_queryset(self, **kwargs):
user = self.request.user
course = Courses.objects.filter(title__in=user.courses.title)
I tried so many code but none of them worked,please any one can help me how can I write this view?
as I said I want to call courses that have same id or title with user courses
If you want to show all Courses of this user, change your code:
def get_queryset(self, **kwargs):
user = self.request.user
course = Courses.objects.filter(user_courses=user) # <- this
# or
course = user.courses.all() # <- this
Also, be sure to add Many to many object properly:
course_data = {'title': 'Django', 'description': 'Django course', 'active': True, 'default_course': True}
course = Courses.objects.create(**course_data)
user = MyUser.objects.create_user(username='test', password='test')
user.courses.add(course) # <- this
Can take a look at this file:
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
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.
I have a custom user model and a company model:
class User(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
company = models.ForeignKey(
Company, null=True, blank=False, on_delete=models.SET_NULL)
class Company(models.Model):
company_name = models.CharField(
default='', max_length=128, blank=True, null=True)
In settings.py I also have a customer_name constant:
CUSTOMER_NAME = os.environ.get('CUSTOMER_NAME')
How can I add a condition in my user model so that if the user is_staff boolean is TRUE then the company_name is fixed to be the CUSTOMER_NAME constant?
Do you have two options:
1) Option 1: Overriding save ( Overriding predefined model methods )
from django.conf import settings
class User(AbstractUser):
username = None
...
company = models.ForeignKey(
Company, null=True, blank=False, on_delete=models.SET_NULL)
def save(self, *args, **kwargs):
if self.is_staff:
#company_name = os.environ.get('CUSTOMER_NAME')
company_name = settings.CUSTOMER_NAME
target = Company.objects.get_or_create( company_name = company_name )
serf.company = target
super().save(*args, **kwargs) # Call the "real" save() method.
2) Option 2: Using pre-save signal:
from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.conf import settings
#receiver(pre_save, sender=User)
def my_handler(sender, **kwargs):
if self.is_staff:
#company_name = os.environ.get('CUSTOMER_NAME')
company_name = settings.CUSTOMER_NAME
target = Company.objects.get_or_create( company_name = company_name )
serf.company = target
The best approach to do this is to override the save function of your model like this:
class User(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
company = models.ForeignKey(
Company, null=True, blank=False, on_delete=models.SET_NULL)
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
if self.instance.id is None and self.is_staff is True: # instance.id is None indicates the instance is new and not an existing one
constant_company = Company('company_name'=CUSTOMER_NAME) # You could also search for an existing company with the CUSTOMER_NAME
constant_company.save()
self.company = constant_company
super().save(force_insert, force_update, using, update_fields)
This way will ensure you each time a staff user is saved no matter where a company with your constant name will be linked to it.
I've been trying to store value of one checkbox, promo_consent, sent from a form into a new column that I've just created in the DB.
Whatever I do it stores always TRUE no matter wheter the checkboxed was checked or not, or stores always FALSE no matter wheter the checkboxes was checked or not.
I have this model:
class User(AbstractBaseUser, PermissionsMixin, PagePermissionMixin):
"""User model for both staff and clients.
It consists of base AbstractBaseUser class and has 2 permissions mixins.
One of them is for standard django permissions and the second is
for Page object permissions.
Note:
This model is used for OAuth2 and Django authentication.
"""
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email address'), unique=True, blank=True)
new_email = models.EmailField(_('new email'), blank=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this admin '
'site.'))
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(
_('date joined'),
default=timezone.now)
promo_consent = models.BooleanField(
_('Promo consent'),
default=False,
help_text=_('Shows whether user has agreed to be notified about '
'news and promo sales'))
....
....
....
and this serializer:
class RegistrationSerializer(SerializerSchemaMixin, serializers.Serializer,
SerializerValidateMixin,
EmailUniquenessValidationMixin,
PasswordValidationMixin):
"""Registration serializer."""
first_name = serializers.CharField(max_length=30, default='')
last_name = serializers.CharField(max_length=30, default='')
email = serializers.EmailField(required=True)
password = serializers.CharField(max_length=100, required=True)
password2 = serializers.CharField(max_length=100, required=True)
rules = serializers.BooleanField(required=True)
promo_consent = serializers.BooleanField(required=False)
def validate_rules(self, value):
"""Checks if 'rules' is True."""
if not value:
raise serializers.ValidationError(_('Rules has to be checked'))
else:
return value
def promo_consent(self, value):
return true
def validate(self, data):
"""Override serializer.validate()."""
self.validate_passwords_uniformity(data)
return data
def save(self, **kwargs):
"""Register new user and send confirmation email."""
language = kwargs['language']
email = self.validated_data['email']
promo_consent = self.promo_consent
self.instance = User(first_name=self.validated_data['first_name'],
last_name=self.validated_data['last_name'],
email=email,
is_active=False,
email_confirmation=uuid.uuid4().hex)
self.instance.set_password(self.validated_data['password'])
self.instance.save()
self.instance.send_email_confirmation(language, email)
return self.instance
I've been working this the second day. What am I missing here?