Django AbstractBaseUser MultipleChoiceField - python

I have created a custom user model with AbstractBaseUser like this:
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
preference = models.CharField(max_length=400)
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'preference']
objects = CustomUserManager()
def __str__(self):
return self.email
For the preference field i don't want a char field, but to create a MultipleChoiceField and when a user sign up to choose what he/she wants from the choices. Is there a simple way to do this?
I have a similar form which i used for different purpose:
class CategoryForm(forms.Form):
def __init__(self, *args, **kwargs):
categories = kwargs.pop("Category")
super(CategoryForm, self).__init__(*args, **kwargs)
self.fields["Category"] = forms.MultipleChoiceField(choices=categories, label='Click this to select categories')
EDIT
class CustomUser(AbstractBaseUser, PermissionsMixin):
category_list = pickle.load(open("/home/anonymous/Documents/Diploma-Recommender/Recommendation/Dataset"
"/category_list.pickle", "rb"))
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
category_tuple = ((),)
for j in category_list:
category_tuple = category_tuple + ((j, j),)
category_tuple = list(category_tuple)
category_tuple.pop(0)
category_tuple = tuple(category_tuple)
preference = ArrayField(
models.CharField(choices=category_tuple, null=True, max_length=50, blank=True, default=None),
)
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'preference']
objects = CustomUserManager()
def __str__(self):
return self.email

I would recommend using an ArrayField in your model if you are using postgreSQL (which you should be!). This will accomplish your goal of multiple choices in a model field.
from django.contrib.postgres.fields import ArrayField
class CustomUser(AbstractBaseUser, PermissionsMixin):
CATEGORY_1 = 'Category_1'
CATEGORY_2 = 'Category_2'
CATEGORY_3 = 'Category_3'
CATEGORY_TYPE_CHOICES = [
(CATEGORY_1, 'Category_1'),
(CATEGORY_2, 'Category_2'),
(CATEGORY_3, 'Category_3')
]
category = ArrayField(
max_length=10,
choices=CATEGORY_TYPE_CHOICES,
null=True,
default=None,
blank=True
)
Read more here: Django Model MultipleChoice

if your multiple choice is sth like active diactive
you can just specify those like this :
CHOICES = (('one','one'), ('two','two') ...)
preference = models.CharField(max_length=400, choices = CHOICES)
this works if you want to get the gender or some limited choices , but if your choices is from different model like category and there is a model Category if the number of choices is 1 ForeignKey and if it is more than 1 use ManyToMany relation in your User model
and if you use ModelForm django handles it for you.

Related

Set the value of a field in a model as the value of a field in another model in django

I have a two model field one which is the user model and one which is the landlord model. I want the first_name and last_name of the user model to be saved also in the landlord model.
This is my model view
pass
class User(AbstractUser):
is_customer = models.BooleanField(default=False)
is_employee = models.BooleanField(default=False)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
nin = models.IntegerField(unique = True , null=True)
avatar = models.ImageField(null= True, default="avatar.svg")
objects = UserManager()
class Landlord(models.Model):
user = models.OneToOneField(User, null= True, on_delete=models.CASCADE)
first_name = models.CharField(max_length=200, null=True)
last_name = models.CharField(max_length=200, null=True)
email = models.EmailField(unique = True , null=True)
bio = models.TextField(null=True)
nin = models.IntegerField(unique = True , null=True)
avatar = models.ImageField(null= True, default="avatar.svg")
USERNAME_FIELD = 'email'
REQUIRED_FIELDS= []
objects = User()
def __str__(self):
return str(self.user)```
Instead of creating such model decide to do one of solutions:
Inherit from User model:
class Landlord(User):
Make User universal model with a flag if it is a Landlord user:
class User(AbstractUser):
...
is_landlord = models.BooleanField(default=False)
With option 2 just everywhere you need only Landlord things use if user.is_landlord: or in templates: {% if user.is_landlord %} etc.

how to filter items in django

I have some users in my application where some are admin and some are suppliers, I will like to filter only those that are suppliers. I have tried using some queryset but I am not getting it. I will also like some recommendation where I can learn more about to filter objects in Django or python. Thanks
models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
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)
# CUSTOM USER FIELDS
firstname = models.CharField(max_length=30)
lastname = models.CharField(max_length=30)
telephone = models.IntegerField(blank=True, null=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
class user_type(models.Model):
is_admin = models.BooleanField(default=False)
is_supplier = models.BooleanField(default=False)
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
if self.is_supplier == True:
return User.get_email(self.user) + " - is_supplier"
else:
return User.get_email(self.user) + " - is_admin"
views.py
def Viewsupplier(request):
suppliers = User.objects.filter(i am getting stuck here with the appriopriate filter)
context = {"suppliers":suppliers}
print(suppliers)
return render(request, 'core/view-suppliers.html', context)
You cann filter with:
suppliers = User.objects.filter(user_type__is_supplier=True)
If you define a relation (like a ForeignKey or OneToOneField), you can access the relation in reverse as well. If you do this in a query, It uses the related_query_name=… [Django-doc] as name for the relation in reverse. If you did not fill this in, it will take the related_name=… [Django-doc], and finally, as is here the case, default to the model name in lowercase.
We thus here filter the User objects such that we only retrieve Users for which there is a related user_type where is_supplier is True.

django foreign key relationships

models.py
class Hub(models.Model):
name = models.CharField(max_length=150)
def __str__(self):
return self.name
class User(AbstractUser):
is_client = models.BooleanField(default=False)
is_trainer = models.BooleanField(default=False)
username = models.CharField('username', max_length=150, unique=True)
email = models.EmailField(unique=True)
hub = models.ForeignKey(Hub, on_delete=models.CASCADE, blank=True, null=True)
hub_position = models.CharField(max_length=150, default="")
mentor = models.ForeignKey('self', on_delete=models.CASCADE, blank=True,null=True)
terms = models.BooleanField(blank=True, default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'terms']
def get_absolute_url(self):
return reverse('student:dashboard', kwargs={'pk': self.pk})
Confused on how to design the models here. Each User can belong to exactly one Hub.A hub has one leader, many excoms and many members ,all of them belongs to User .The hubs are added from the admin side.Leader can accept hub joining requests from excoms and members.
I'd add the user position as a choice field to the User, so you get a nice select box in the Admin.
class User(AbstractUser):
USER_POSITIONS = ((0, 'Regular'), (1, 'Leader'), (2, 'Excom'))
hub = models.ForeignKey(Hub, on_delete=models.CASCADE, blank=True, null=True)
hub_position = models.IntegerField(default=0, choices=USER_POSITIONS, ...)

How do i create a new proxy model based on another model in django?

I have a model named tranasaction.
class transactions(models.Model):
id = models.AutoField(primary_key=True)
date = models.DateTimeField(default=datetime.now, blank=True)
saleduser = models.ForeignKey('UserData',on_delete=models.CASCADE, related_name='vclouduser_data', blank=True, null=True)
brand = models.CharField(max_length=50,blank=True)
type = models.CharField(max_length=50,blank=True)
quantity = models.DecimalField(blank=True,null=True,max_digits=20,decimal_places=2)
amount = models.DecimalField(blank=True,null=True,max_digits=20,decimal_places=2)
And I need to create a summary report,
so I create a new Model.
class SaleSummary(transactions):
class Meta:
proxy = True
verbose_name = 'Sale Summary'
verbose_name_plural = 'Sales Summary'
what i need that i need to get the total amount of each type as a new model.
please help me to solve this.
Thanks in advance.
Here is an example of a proxy model for a normal model, with a filtering example. I hope it will be helpful for you that how can you create the proxy model and how can you filter specific data from any model for the admin site. You also can apply this for your custom API response, Then you should write this code in serializers. Best of luck.
models.py
class UserModel(AbstractBaseUser):
"""
Purpose: create a custom auth user table
"""
name = models.CharField('name of user',max_length=256)
email = models.EmailField('email address', unique=True)
date_joined = models.DateTimeField('user creation date', auto_now_add=True)
is_admin = models.BooleanField('is a admin', default=False)
is_staff = models.BooleanField('is a staff', default=False)
is_superuser = models.BooleanField('if a superuser', default=False)
status = models.ForeignKey(SesameUserStatus, on_delete = models.CASCADE, related_name='sesame_user_status_type', default=2)
organization = models.ForeignKey(Organization, on_delete = models.CASCADE, related_name='sesame_user_organization_info', default=1)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def has_perm(self,prm,obj=None):
return self.is_active and self.is_admin
def has_module_perms(self,app_level):
return self.is_active and self.is_admin
def __str__(self):
return f'{self.name} // {self.email} // {self.organization.name}'
class Meta:
verbose_name = "User"
verbose_name_plural = "Users"
indexes = [
models.Index(fields=['email']),
]
class UserProxyModel(UserModel):
"""
Purpose: create proxy model to visualize only pending user
"""
class Meta:
proxy = True
verbose_name = "Pending User"
verbose_name_plural = "Pending Users"
###########################################################################
admin.py
class UserAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'email', 'date_joined', 'is_admin', 'is_staff']
class Meta:
model = UserModel
class UserProxyModelAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'email', 'date_joined', 'is_admin', 'is_staff', 'organization', 'status']
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs.filter(status=SESAME_USERS["status"]["PENDING"]).order_by('id')
return None
class Meta:
model = UserProxyModel
admin.site.register(UserModel, UserAdmin)
admin.site.register(UserProxyModel, UserProxyModelAdmin)

One to One relationship serializing in django

I have the following User,
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, max_length=255)
username = models.CharField(null=False, unique=True, max_length=255)
full_name = models.CharField(max_length=255, blank=True, null=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
And the following UserProfile model,
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, )
level = models.CharField(default="Noob", max_length=255)
reputation = models.IntegerField(default=0)
status = models.CharField(max_length=255, null=True, blank=True)
The User has a one to one relationship with Profile.
This is the UserSerializer,
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
location = LocationSerializer(read_only=True)
profile = UserProfileSerializer(read_only=True)
class Meta:
model = models.User
fields = (
'id', 'email', 'mobile', 'username', 'full_name', 'password', 'is_active', 'profile',
)
And this is the profile serializer.
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserProfile
fields = ('level', 'reputation', 'status',)
The issue is that in the serialized output for the user there is no nested profile data. How do I fix this. Any help appreciated.
all you need is set source for profile:
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
location = LocationSerializer(read_only=True)
profile = UserProfileSerializer(source='userprofile', read_only=True)
the userprofile is name of relation of your model User by onetoone to the UserProfle, other way you can set related_name for attribute user in the
UserProfle.
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile', on_delete=models.CASCADE)
then your serializer will work fine as is.

Categories

Resources