How to get count items in foreign key Django? - python

I have two classes of models and I need to get the number of products from a single vendor
class Vendor(models.Model):
name = models.CharField(max_length=50, unique=True)
seo_name = models.SlugField()
product_count = models.IntegerField(default=0)
class Product(models.Model):
vendor = models.ForeignKey(Vendor, unique=False, blank=True, default=None, null=True, on_delete=models.SET_NULL)
How to calculate the count of products in the Vendor ?

Take a look on Django recipe: Add an auto-count field to your model
tutorial. It totally covers your question.
Good Luck !

Related

Should I use oneToMnay or ManyToMany in django

I am new in django and trying to create a website where I can search for vehicles and see what parts I have for this vehicle.
I have two databases, one with vehicles and one with parts:
class Vehicle(models.Model):
vehicle_id = models.BigIntegerField(primary_key=True)
vehicle = models.CharField(max_length=255)
def __str__(self):
return self.vehicle
class Part(models.Model):
part_id = models.BigIntegerField(primary_key=True, db_column='part_id')
part_name = models.CharField(max_length=255, db_index=True, null=True)
catalog_code = models.CharField(max_length=255, null=True)
price = models.CharField(max_length=255, default=None, null=True)
description = models.CharField(max_length=255, default=None, null=True)
vehicle_id = models.ForeignKey(Vehicle, on_delete=models.PROTECT, null=True)
def __str__(self):
return self.part_name
Now I using oneToMany, but can't figure out if it is correct and how can I see all parts for one vehicle
You implemented the relationship correctly. One to many is a way to go here.
You can make your life easier by defining related_name in the ForeighKey:
vehicle_id = models.ForeignKey(Vehicle, on_delete=models.PROTECT, null=True, related_name="parts")
and use the following constructs when referring to the vehicle parts:
myvehicle.parts.all()
myvehicle.parts.filter(part__part_id=1)
Side comment: I do not think that it was a good idea to define id fields explicitly. Django sets model id fields automatically (and defines them as primary keys).

Solution to filter by Cumulative sum and error: Window is disallowed in the filter clause

This is follow-up to a question to:
Filter Queries which sum of their amount field are greater or lesser than a number
which is supposed to be solved. Answer suggests using Window function with filter but this results in a error:
django.db.utils.NotSupportedError: Window is disallowed in the filter clause.
Comment from #atabak hooshangi suggests removing the Window function, but query doesn't work in intended way after that. Any ideas to solve this problem?
let's say we have these 2 models:
class Developer(models.Model):
first_name = models.CharField(max_length=40, null=False, blank=False,
unique=True)
last_name = models.CharField(max_length=40, null=False, blank=False,
unique=True)
profession = models.CharField(max_length=100, null=False)
cv = models.FileField(upload_to=upload_cv_location, null=True, blank=True)
description = models.TextField()
img = models.ImageField(upload_to=upload_location, null=True, blank=True)
class Meta:
verbose_name = 'Developer'
verbose_name_plural = 'Developers'
ordering = ('first_name',)
def __str__(self):
return f'{self.first_name} {self.last_name}'
class Skill(models.Model):
developer = models.ForeignKey(to=Developer, on_delete=models.CASCADE)
category = models.ForeignKey(to=SkillCategory, on_delete=models.SET_NULL,
null=True)
name = models.CharField(max_length=50, null=False)
priority = models.PositiveIntegerField()
class Meta:
ordering = ('-priority',)
def __str__(self):
return f'{self.name} skill of {self.developer}'
As you can see , we have a developer model which has relationship with skill. Each developer can have multiple skills.
now consider we want to get the developers whos sum of their priorities are greater than a number.
The orm query should work this way :
from django.db.models import Sum
developers = Developer.objects.annotate(tot=Sum('skill__priority')).filter(tot__gt=250).all()
The output will be the developers who has greater than 250 priority_sum .
You can filter tot which is an annotated variable in any way you want.
like .filter(tot__lte)
or
.filter(tot__lt)
I hope this is what you were looking for.

Django: how to count posts related to a category in django?

i have a model class Category and also a model class Course. i want to count all the courses that are related to a model e.g: Web Devlopment - 26 Courses i dont know how to go about this since the this are two diffrent models.
class Category(models.Model):
title = models.CharField(max_length=1000)
class Course(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
course_title = models.CharField(max_length=100, null=True, blank=True)
course_category = models.ForeignKey(Category, on_delete=models.DO_NOTHING, null=True, blank=True)
First, you need to set the related_name attribute in the course_category field.
class Course(models.Model):
...
course_category = models.ForeignKey(Category, realted_name="courses" on_delete=models.DO_NOTHING, null=True, blank=True)
Next, you can use this name to aggregate the query as the following.
from django.db.models import Count
cateogries = Category.objects.annotate(number_of_courses = Count("courses")).all()
Then, each of the categories will have the number_of_courses field that indicates the number of courses.

Is there a way to query reverse in django models?

I know this question has been answered in different ways but i'm still unable to see the clear picture.
I have the following tables with following relationships:
class Category(models.Model):
name = models.CharField(max_length=100, null=False, blank=False)
def __str__(self):
return self.name
class SubCategory(models.Model):
sub_name = models.CharField(max_length=100, null=False, blank=True, default='None')
category = models.ManyToManyField(Category, default=1)
class Product(models.Model):
name = models.CharField(max_length=150, null=False, blank=False)
brand = models.CharField(max_length=100, null=False, blank=False)
price = models.FloatField(null=False, blank=False)
weight = models.CharField(max_length=100,null=False, blank=False)
sub_category = models.ForeignKey(SubCategory, on_delete=models.SET_DEFAULT, default=13)
category = models.ForeignKey(Category, on_delete= models.CASCADE)
I am trying to solve two queries as follows:
Fetch all the category and subcategories to a specific category where the brand is given. Display structure that i'm making is Brand(Men->Shirts,Pants etc. Women->Shirts,Pants etc).
NOTE: Each brand can sell products of multiple categories and subcategories.
Fetch all the subcategories where the category name must be taken out from the result of Category.objects.all(). Display structure that i'm making here is Men(its sub categories) , Women(its sub categories)
Let us take it step by step
Get all products for a specific brand
Product.objects.filter(brand=brand)
Now we want to list down the categories for this match. We'll get the ids of categories instead
Product.objects.filter(brand=brand).values_list("category_id", flat=True)
Now let us get the corresponding category objects
queryset = Product.objects.filter(brand=brand).values_list("category_id", flat=True)
categories = Category.objects.filter(id__in=queryset)
Note: If you just want to fetch the category names, you can do
Product.objects.filter(brand=brand).values_list("category__name", flat=True).distinct()

filter on foreign and many to many relationship field

I'm struggling getting the right query for my project. Here is an example of my model :
from django.db import models
class Brand(models.Model):
name = models.CharField(max_length=30)
handle = models.SlugField(max_length=30, unique=True, null=True, blank=True)
def __unicode__(self):
return self.name
class Product(models.Model):
product_id = models.SlugField(unique=True)
brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, blank=True, null=True)
collections = models.ManyToManyField('Collection')
def __unicode__(self):
return self.product_id
I am trying to get all the Brand_name based on the value of the Product.collection
Eg: Shoes is a Product.collection, I want to get all the Brand_name for collection - shoes
I tried __ method also. Somehow it is not working.
You should try something like this:
Brand.objects.product_set.filter(collections__name="Shoes").values('brand__name')
Brand.objects.filter(
product__collection=product.collection
).values_list('name', flat=True).distinct()
product is instance of Product.
Add a related_name to your foreign key like below,
brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, blank=True,
null=True, related_name='products')
And then you can try below query and it'll return you a list of all the Brand.name which has product__collections_name='Shoes'.
Brand.objects.filter(products__collections__name='Shoes').values_list('name', flat=True)

Categories

Resources