Django Model object creation method - django

I'm having two models where UserGroup model, which contains a group admin, and DetailedUser model which related to the group model, where the field user points all users in the certain UserGroup, I want to add a field that when a new user added to the group it store its date and time of user added to the particular group.
class UserGroup(models.Model):
group_admin = models.ForeignKey(User, on_delete=models.CASCADE, related_name='group_by')
group_name = models.CharField(max_length=100)
group_amount = models.PositiveSmallIntegerField()
def __str__(self):
return self.group_name
class DetailedUser(models.Model):
group = models.ForeignKey(UserGroup, on_delete=models.CASCADE, related_name='user_group')
user = models.ManyToManyField(
User, related_name='single_user')
user_added = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return f"{self.group.group_name}"
How can I done this method?

I think your model design is not correct. What you need(I think) is ManyToManyField with though. For example:
class UserGroup(models.Model):
group_admin = models.ForeignKey(User, on_delete=models.CASCADE, related_name='group_by')
group_name = models.CharField(max_length=100)
group_amount = models.PositiveSmallIntegerField()
members = models.ManyToManyField(User, through="DetailedUser")
def __str__(self):
return self.group_name
class DetailedUser(models.Model):
group = models.ForeignKey(UserGroup, on_delete=models.CASCADE, related_name='user_group')
user = models.ForeignKey(
User, related_name='single_user')
user_added = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return f"{self.group.group_name}"
Usage example:
>> group = UserGroup.objects.get(pk=1)
>> user = User.objects.first()
>> DetailedUser.objects.create(group=group, user=user)
>> group.memebers.all()

Related

Filter queryset of django inline formset based on attribute of through model

I have a basic restaurant inventory tracking app that allows the user to create ingredients, menus, and items on the menus. For each item on a given menu, the user can list the required ingredients for that item along with a quantity required per ingredient for that item.
Menu items have a many-to-many relationship with ingredients, and are connected via an "IngredientQuantity" through table.
Here are my models:
class Ingredient(models.Model):
GRAM = 'Grams'
OUNCE = 'Ounces'
PIECE = 'Pieces'
UNIT_CHOICES = [
('Grams', 'Grams'),
('Ounces', 'Ounces'),
('Pieces', 'Pieces')
]
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=200)
unitType = models.CharField(max_length=200, choices=UNIT_CHOICES, verbose_name='Unit')
unitCost = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='Unit Cost')
inventoryQuantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='Quantity')
def __str__(self):
return self.name + ' (' + self.unitType + ')'
def totalCost(self):
result = self.inventoryQuantity * self.unitCost
return "{:.0f}".format(result)
class Menu(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=200)
timeCreated = models.DateTimeField(auto_now_add=True)
timeUpdated = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.name)
class MenuItem(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=10, decimal_places=2)
ingredients = models.ManyToManyField(Ingredient, through='IngredientQuantity')
menu = models.ForeignKey(Menu, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.name
def itemCost(self):
relevantIngredients = IngredientQuantity.objects.filter(menuItem=self)
cost = 0
for ingredient in relevantIngredients:
cost += (ingredient.ingredient.unitCost * ingredient.ingredientQuantity)
return cost
class IngredientQuantity(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
menuItem = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
ingredientQuantity = models.IntegerField(default=0)
def __str__(self):
return str(self.ingredient)
This is a multi-user app, so when a user creates a new item on a menu and adds ingredients to it, they should only have the option of choosing ingredients they have created, not those of other users. Here is my attempt to do that in my views:
def ItemUpdate(request, pk):
item = MenuItem.objects.get(id=pk)
user = request.user
IngredientQuantityFormset = inlineformset_factory(
MenuItem, IngredientQuantity, fields=('ingredient', 'ingredientQuantity'), can_delete=True, extra=0
)
form = ItemCreateForm(instance=item)
formset = IngredientQuantityFormset(instance=item, queryset=IngredientQuantity.objects.filter(ingredient__user=user))
if request.method == 'POST':
form = ItemCreateForm(request.POST, instance=item)
formset = IngredientQuantityFormset(request.POST, instance=item, queryset=IngredientQuantity.objects.filter(ingredient__user=user))
# rest of view...
I've searched everywhere for how to implement the queryset parameter properly, but I cannot get it to work. When creating an item on a menu, the user still has the ability to choose from every ingredient in the database (including the ones created by other users). I would like the user to only be able to choose from the ingredients they themselves created.
Does anyone know how to do this properly? Thank you!
I received some guidance on Django forums and arrived at a solution which is documented below:
https://forum.djangoproject.com/t/filter-dropdown-options-in-django-inline-formset-based-on-attribute-of-through-model/13374/3

how to have database relationship with the active data. in django

i have some active and non active data's in EVENT models and active data has the VISITORS form to fill ..so far i have tried OnetoOne relationship but it didn't succeed ..i am getting both active and non active field in VISITORs model..thank you for your time.
here is models.py
class Event(models.Model):
event_id = models.AutoField
Event_Name = models.CharField(max_length=50)
description = RichTextField()
date_And_time = models.DateTimeField()
location=models.CharField(max_length=50)
slugs = models.SlugField(max_length= 200,default="")
picture = models.ImageField(upload_to='wildlife/picture', default="")
active = models.BooleanField(default=False)
class Meta:
ordering = ["date_And_time"]
def __str__(self):
return self.Event_Name
class Eventvisitor(models.Model):
event = models.OneToOneField(Event, on_delete=models.CASCADE, related_name="eventvistor",default="")
name = models.CharField(max_length=50)
email = models.CharField(max_length=70, default="")
phone = models.CharField(max_length=20,default="")
date = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-date']
def __str__(self):
return self.email
You can limit the choices with limit_choices_to=… [Django-doc]. But likely what you want is a ForeignKey, since otherwise, each Event can have at most one related EventVisitor (a OneToOneField is basically a ForeignKey with a unique=True constraint).
class Eventvisitor(models.Model):
event = models.ForeignKey(
Event,
limit_choices_to={'active': True},
on_delete=models.CASCADE,
related_name='eventvistors'
)
name = models.CharField(max_length=50)
email = models.CharField(max_length=70, default="")
phone = models.CharField(max_length=20,default="")
date = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-date']
def __str__(self):
return self.email
Note that while one can only select Events with active=True, if you later set the .active field to False, items will still link to it, since the relation is not enforced at database level.

How to save multiple object in a single POST request

I am new to DRF
I am saving a user details and his pets details .
Here is the model
class Users(models.Model):
id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=255, blank=True)
last_name = models.CharField(max_length=255, blank=True)
job = models.CharField(max_length=255, blank=True)
age = models.CharField(max_length=255, blank=True)
class PetDetails(models.Model):
user = models.ForeignKey(
Users, on_delete=models.CASCADE, blank=True, null=True)
pet_name = models.CharField(max_length=255, blank=True)
pet_color = models.CharField(max_length=255, blank=True)
pet_category = models.CharField(max_length=255, blank=True)
In this I need to save both user and his pets in a single Post request.
So I created a serializer like this
class UserCreateSerializer(ModelSerializer):
pet = PetDetailCreateSerializer(many=True)
class Meta:
model = Users
fields = ['first_name','last_name','job','age', 'pet']
def create(self, validated_data):
pets_data = validated_data.pop('pet')
user_obj = Users.objects.create(**validated_data)
for pet in pets_data:
PetDetails.objects.create(user=user_obj, **pet)
return user_obj
The issue I am facing is if a single person can have multiple pets.
For Example John is a user and he having two Pets.
So in this cases two users object will creating .How to resolve this
OR is there any other methods for handling this
My views is
class UserCreateView (CreateAPIView):
serializer_class = UserCreateSerializer
One way is to check if user already exists by using get_or_create:
user_obj = Users.objects.get_or_create(**audit_data)
But better way, I think, is to create user with multiple pets instead:
class UserCreateSerializer(ModelSerializer):
petdetails_set = PetDetailCreateSerializer(many=True)
class Meta:
model = Users
fields = ['first_name','last_name','job','age', 'petdetails_set']
def create(self, validated_data):
pets_data = validated_data.pop('pet')
user_obj = User.objects.create(**validated_data)
for pet in pets_data:
PetDetails.objects.create(user=user_obj, **pet)
return user_obj
Also, I advice to use separate endpoints/serializers for user creation.

Django design model - when a data of status field changes, remaining models status change with it

Its my first time trying django as my first programming project.
I have a hierarchy structure of Company -> Business -> Outlets using foreign key.
I would like to know is there anyway to structured it in a way where the Company status is saved as inactive status, the remaining business, outlets models that will be triggered as inactive status.
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Common_Info(models.Model):
"""(Common description)"""
name = models.CharField(blank=True, max_length=100)
slug = models.SlugField(unique=True, max_length=120)
address_1 = models.CharField(max_length=50, null=True)
address_2 = models.CharField(max_length=50, null=True)
address_3 = models.CharField(max_length=50, null=True)
post_code = models.CharField(max_length=6, null=False)
registration_no. = models.CharField(max_length=15,null=False)
gst_no. = models.CharField(max_length=15,null=True)
telphone_no. = models.CharField(max_legth=15, null=False)
fax_no. = models.CharField(max_legth=15, null=True)
email_address = models.EmailField(max_length=254,null=False)
"""(Status choice)"""
Active_Status = 1
Inactive_Status = 0
STATUS_CHOICES = (
(Active_Status, 'Active'),
(Inactive_Status, 'Inactive'),
)
status = models.IntegerField(choices=STATUS_CHOICES, default=Active_Status)
create_date = models.DateTimeField(auto_now_add=True)
create_user = models.ForeignKey(settings.AUTH_USER_MODEL)
modified_date = models.DateTimeField(auto_now_add=True)
modified_user = models.ForeignKey(settings.AUTH_USER_MODEL)
class Meta:
abstract = True
class Company(Common_Info):
"""(Company additional description)"""
gst_no. = models.CharField(max_length=15,null=True)
class Meta:
verbose_name ='Company'
verbose_name_plural = "Companies"
def __unicode__(self):
return u"Company"
class Business(Common_Info):
"""(Business description)"""
parent=models.ForeignKey(Company, on_delete=models.CASCADE)
gst_no. = models.CharField(max_length=15,null=True)
class Meta:
verbose_name ='Business'
verbose_name_plural = "Businesses"
def __unicode__(self):
return u"Business"
class Outlet(Common_Info):
outlet_code = models.CharField(max_length=3, unique=True)
business_name = models.ForeignKey(Business, on_delete=models.CASCADE)
def __unicode__(self):
return u"Outlet"
Is there something similar to cascade on delete or other more elegant way of extending such a function across other apps in the project.
I don't think there is any direct support in ORM. But you can override the save() method to update the related the outlets and business. You can use related objects to fetch business and outlets. Here is an example:
class Company(Common_Info):
"""(Company additional description)"""
gst_no. = models.CharField(max_length=15,null=True)
class Meta:
verbose_name ='Company'
verbose_name_plural = "Companies"
def __unicode__(self):
return u"Company"
def save(self, *args, **kwargs):
super(Company, self).save(*args, **kwargs)
if self.status == 0:
self.business_set.update(status=self.status)
self.outlet_set.update(status=self.status)

Get queryset of many-to-many field under another many-to-many field

I am working on a User/Role/Permission model in django, where the model structure is this.
class GlobalPermission(BasicAbstractClass):
TYPE_CHOICES = ["user_level", "platform_level", "user_platform_access_level"]
short_code = models.CharField(max_length=64, blank=True, null=True)
name = models.CharField(max_length=92, blank=True, null=True)
description = models.CharField(max_length=189, blank=True, null=True)
type = EnumField(choices=TYPE_CHOICES, blank=True, null=True)
def __str__(self):
return self.name
class Meta:
db_table = 'global_permission'
class Role(BasicAbstractClass):
ROLE_CHOICES = ["admin", "analyst", "moderator", "editor", "superuser", "developer"]
SERVICE_CHOICES = ["social_media_management", "survey"]
service = EnumField(choices=SERVICE_CHOICES)
name = EnumField(choices=ROLE_CHOICES)
permissions = models.ManyToManyField(GlobalPermission, related_name="role_permissions", blank=True, through="RolePermission")
def __str__(self):
return self.name + " of " + self.service
class Meta:
db_table = 'role'
class RolePermission(models.Model):
role = models.ForeignKey(Role, on_delete=models.CASCADE)
permission = models.ForeignKey(GlobalPermission, on_delete=models.CASCADE)
def __str__(self):
return str(self.id)
class Meta:
db_table = "role_permissions"
class UserAccount(models.Model):
roles = models.ManyToManyField(Role, related_name="+", blank=True, through="UserRole")
class UserRole(BasicAbstractClass):
user = models.ForeignKey(UserAccount, on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE)
def __str__(self):
return str(self.id)
class Meta:
db_table = "user_role"
What I want here, is to get the list of permissions of a user. Here, the user may be assigned multiple roles, and I want a queryset containing all the permissions for those roles.
Start with the thing you want (GlobalPermission) and then work backwards in the query:
GlobalPermission.objects.filter(role_permissions__user_accounts=target_user).distinct()
Note that you need a way to reference UserAccount in a query, such as:
class UserAccount(models.Model):
roles = models.ManyToManyField(Role, blank=True, through="UserRole",
related_name="+", related_query_name="user_accounts")