I have two models
class Product(models.Model):
name = models.CharField(max_length=50)
averageRating = models.IntegerField(null=True, blank=True)
ratingCount = models.IntegerField(null=True, blank=True)
cover = models.ImageField(upload_to='images/', default=None, blank=True, null=True)
...
and
class VariantProduct(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
mainPrice = models.IntegerField()
discountPrice = models.IntegerField(null=True, blank=True)
this means different variant of products have different prices.
I need the variant of each product that have minimum mainPrice
in SQL i think this code works for my purpose
SELECT *, min(discountPrice) as minPrice
FROM variant GROUP BY product
but I don't know how can I get this result in Django
You can use an annotation to attach the minimum price of VariantProducts attached to Product objects:
from django.db.models import Min
Product.objects.annotate(minimum_main_price=Min('variantproduct__mainPrice'))
Related
I am working on a project named "Super Market Inventory Management System". There are some models requiring many-to-many relation among them.
I tried to add ManyToManyField(to=model, on_delete=models.CASCADE). However, it works but I need to add some extra fields to the bridge table between the two tables.
How can I do It?
Given below is my models.py
class Purchase(models.Model):
pay_status = models.CharField(max_length=50, choices=PAYSTATUS_CHOICES, default="Pending")
date_of_purchase = models.DateTimeField(auto_now_add=True)
last_payment = models.DateTimeField(auto_now=True)
class Product(models.Model):
name = models.CharField(max_length=200)
barcode = models.IntegerField(blank=True, null=True)
description = models.TextField(blank=True, null=True)
# image =
weight = models.TextField(blank=True, null=True)
status = models.BooleanField(default=True)
price = models.FloatField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class PurchaseProduct(models.Model):
purchase_id = models.ForeignKey(to=Purchase, on_delete=models.CASCADE)
product_id = models.ForeignKey(to=Product, on_delete=models.CASCADE)
unit_price = models.FloatField()
quantity = models.IntegerField()
price = models.FloatField()
In the bridge table I also want to add the unit price and the quantity how can I do?
OR
Is there any alternate way of doing???
However if I do not add unit price and quantity I don't need to create this bridge table all the endings will be done by Django itself but I must require the above mentioned fields in my model
I need to sum all different product's "product_volume" in one for this my model is
class Product(BaseModel, models.Model):
name = models.CharField(max_length=256)
category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL, related_name='product_category')
description = models.CharField(max_length=1000)
hs_code = models.CharField(max_length=256, unique=True)
photo = models.ImageField(upload_to='media/product/%Y/%M/', null=True, blank=True)
production_unit = models.ForeignKey(MeasurementUnit, related_name='product_unit', null=True, blank=True, on_delete=models.SET_NULL)
class Production(BaseModel, models.Model):
product = models.ForeignKey(Product, related_name='production_product', on_delete=models.CASCADE)
district = models.ForeignKey(DistrictLevel, related_name='production_district', on_delete=models.CASCADE)
production_volume = models.FloatField()
production_year = models.ForeignKey(FiscalYear, related_name='production_year', null=True, blank=True, on_delete=models.SET_NULL)
seasons = models.ManyToManyField(Season)
Here, I'm trying to do is that, sum of the product_volume of a product is like,
product1, product_volume=20
product2, product_volume = 40
product1, product_volume = 60
in my table i need to show
product1, product_volume = 80
product2, product_volume = 40
Here is my table
I'm getting result by using for loop but, is there any better solution for this using ORM.
sorry for my English, I'm little weak in English
You can use the Sum aggregation function [Django docs] to annotate the sum of the field:
products = Product.objects.annotate(total_production_volume=Sum('production_product__production_volume'))
for product in products:
print(product.name, product.total_production_volume)
Here production_product is the related name you have set for the field (this name is quite weird product.production_product doesn't feel very good right? Perhaps the related name would have been better off as productions), and we simply used __ to separate it from the field name that we want to sum on.
I have the following related data models
class Cart(models.Model):
products = models.ManyToManyField('assortment.Product', through='CartProduct')
order = models.OneToOneField('Order', on_delete=models.CASCADE, related_name='order_cart', null=True)
user = models.ForeignKey('account.Profile', on_delete=models.CASCADE, related_name='user_carts', blank=True, null=True)
class CartProduct(models.Model):
product = models.ForeignKey('assortment.Product', related_name='product_cartproducts', null=True, on_delete=models.SET_NULL)
cart = models.ForeignKey('Cart', related_name='cart_cartproducts', null=True, on_delete=models.SET_NULL)
count = models.IntegerField(blank=False, null=False, default=1)
class Order(models.Model):
pay_date = models.DateField(auto_now_add=True)
is_paid = models.BooleanField(default=False)
My code below gives an error: invalid argument "products" in prefetch_related:
Order.objects.all().select_related('order_cart').prefetch_related('products')
How can I join all three models in one request?
The query builder continues with the original table (Order), thus you have to specify the fields relative to that or relative to the previously mentioned field. Try one of the following:
'order_cart__products'
'order_cart__cart_cartproducts'
(Notice the double underscore.)
I have a scenario what will be best design for this .
I have a Articles table (like pizza , drink etc)
class Articles(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE , blank=True, null=True)
articlename = models.CharField(max_length=50, null=False, blank=False)
price = models.DecimalField(max_digits=10, decimal_places=2)
category = models.ForeignKey(Categories, on_delete=models.CASCADE)
ingredient = models.ManyToManyField(Ingredient) #done
articleoptionnames = models.ForeignKey(ArticlesOptionsName , on_delete=models.CASCADE)
2nd table is Article options (Like topping (1 time, 2times or 3 times), extra sauce , etc)
class ArticlesOptions(models.Model):
articleoptionrestaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE , blank=True, null=True)
optionname = models.ForeignKey(ArticlesOptionsName, on_delete=models.CASCADE, related_name="optionnames")
min = models.IntegerField()
max = models.IntegerField()
choice_price = models.DecimalField(max_digits=10, decimal_places=2)
choice = models.CharField(max_length=255)
def __str__(self):
return str(self.optionname)
And 3rd Order table
class orders(models.Model):
restaurant=models.ForeignKey(Restaurant, on_delete=models.CASCADE , blank=True, null=True)
articles=models.ForeignKey(Articles, on_delete=models.CASCADE , blank=True, null=True)
articleoptions=models.ManyToManyField(ArticlesOptions)
totalamount=models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return str(self.articles)
Customer will be able to purchase many articles at a time and then every article have multipul article options (for example 4 types of topping and 4 type of sauce user can select many type of topping and many type of sauce ). SO how to make order table in best way ?
Your order table should be split down further to be able to accommodate more than one article and article option. Your article options should be related to the article added to the order and not to the order itself. So, in my opinion, I think your order should look like this,
class Orders(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, blank=True, null=True)
total_amount = models.DecimalField(max_digits=10, decimal_places=2)
And add an order Article model which has the articles specific to that order each with their own option and each option has a quantity.
class OrderArticle(models.Model):
order = models.ForeignKey(Orders, on_delete=models.CASCADE)
article = models.ForeignKey(Articles, on_delete=models.CASCADE)
class OrderArticleOption(models.Model):
article_option = models.ForeignKey(ArticlesOptions, on_delete=models.CASCADE)
order_article = models.ForeignKey(OrderArticle, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
Hope this helps!
Currently, have a database with an Item table and a Stock table. There is a many to many relationship between the two. A single item object can have many sizes. The next step is to assign an 'inStock' options to the item per size.
Any thoughts on acheiving this?
Current models.py
class Stock(models.Model):
size = models.CharField(max_length=30)
stock = models.BooleanField(default=False)
def __str__(self):
return self.size
class Item(models.Model):
title = models.CharField(max_length=250, null=True, unique=True)
price = models.DecimalField(max_digits=8, decimal_places=2)
aw_product_id = models.CharField(max_length=11, null=True) # Removed because multiple products has similar identifer
url = models.URLField(max_length=250) # Removed 'unique=True'as the aw_prod_id will throw an integrity error
image = models.CharField(max_length=1000)
retailer = models.CharField(max_length=250)
category = models.CharField(max_length=100)
featured = models.CharField(max_length=10, default='NO')
gender = models.CharField(max_length=100, null=True)
sizes = models.ManyToManyField(Stock)
uniq_id = models.CharField(max_length=11, null=True, unique=True) # Removed because multiple products has similar identifer
def __str__(self):
return self.title
You can use the through argument to ManyToManyField to specify another model to use for the relationship, with additional fields instead of the autogenerated model that django creates by default.