Django model - how to go about this concept - django

I have a product model with the following:
class Product(models.Model):
name = models.CharField(max_length=255)
handle = models.CharField(max_length=55)
summary = models.CharField(max_length=255, blank=True)
category = models.ForeignKey(Category)
Above is just the product detail, but there are 3 types of pricing:
Standard - normal regular pricing by filling the price field
Variant - pricing with product variants (size, colour, etc.) with their respective prices
Combined - this is a combination of other saved products, with a custom price provided by user.
For 1 and 2 I have the below model. If the product model has more than 1 price on StandardProduct model then I know it has variants.
class StandardProduct(models.Model):
variant_type = models.CharField(max_length=55)
variant_name = models.CharField(max_lenght=55)
product = models.ForeignKey(Product)
sku = models.CharField(max_length=55, blank=True, null=True)
barcode = models.CharField(max_length=55, blank=True, null=True)
selling_price = models.DecimalField(max_length=15, decimal_places=2)
How do I go about creating the CombinedProduct model? The combined product model can have different created products inside (with their quantities). The price is specified by the user. Below is what I have, but I don't know how to approach this.
class CombinedProduct(models.Model):
product = models.ForeignKey(Product)
item = models.ForeignKey(StandardProduct)
quantity = models.DecimalField(max_length=15, decimal_places=2)

How do I go about creating the CombinedProduct model? The combined
product model can have different created products inside (with their
quantities). The price is specified by the user. Below is what I have,
but I don't know how to approach this.
What you probably want is a ManyToManyField with through option.
This is just a very rough sketch up - I don't get your Product/StandardProduct and the relations.
class CombinedProduct(models.Model):
products = models.ManyToManyField(
Product,
through='Combination'
)
class Combination(models.Model):
product = models.ForeignKey(Product)
combined_product = models.ForeignKey(CombinedProduct)
price = models.DecimalField(max_length=15, decimal_places=2)
quantity = models.DecimalField(max_length=15, decimal_places=2)

Related

How to filter a model in case of too complicated database structure?

I want to make a flexible online shop which will allow it's admins to create products and add custom product fields without need to program. I did it, but the final database structure is so complicated that I can't figure out how to filter it.
Let's say there are categories with some products attached to it. Each category has only one unique template, the template holds custom fields names and types(int, char). When a product is created, the corresponding template-like fields are written to another model that holds custom fields names and values.
So, how to filter the product model considering its custom fields values? To clarify, let's say someone created smartphones category, created template with fields "Brand" and "Screen size", added some smartphones and wants to filter phones with brand="Apple" and screen size > 4.5 inches.
I hope that makes sense ^_^
Database structure:
class Category(models.Model):
name = models.CharField(max_length=63)
class Product(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=63)
price = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(1073741823)], null=True, blank=True)
#Template
class CategoryTemplate(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True)
name = models.CharField(max_length=255, null=True, blank=True)
#Model that holds template custom fields
class TemplateField(models.Model):
template = models.ForeignKey(CategoryTemplate, on_delete=models.CASCADE)
name = models.CharField(max_length=255, null=True, blank=True)
is_integer = models.BooleanField(blank=True, default=False)
#Values of custom char product fields
class ProductPropertiesChar(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
property_name = models.CharField(max_length=255, null=True, blank=True)
property_value = models.CharField(max_length=255, null=True, blank=True)
#Values of custom integer product fields
class ProductPropertiesInteger(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
property_name = models.CharField(max_length=255, null=True, blank=True)
property_value = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(1073741823)], null=True, blank=True)
Maybe this will work. Firstly, I'd strongly recommed using explicit related names!
class ProductPropertiesChar(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE,
related_name='charprop')
...
Simple case: all Products related to a single specified ProductPropertiesChar (the default related name is too horrible to type)
results = Product.objects.filter( charprop__property_name='Brand',
charprop__property_value='Apple' )
You can combine several values with __in or use the other usual __ lookups. You should also be able to .exclude(...).
results = Product.objects.filter( charprop__property_name='Brand',
charprop__property_value__in = ['Apple','Samsung','Google'] )
You ought to be able to use Q objects
q1 = Q( charprop__property_name='Brand',charprop__property_value='Apple' )
q2 = Q( intprop__property_name='ScreenSize', intprop__property_value__gte=130 )
I'm pretty sure or will work
results = Product.objects.filter( q1 | q2 )
I'm not quite so sure about and because you are following the related name to two different objects
results = Product.objects.filter( q1 & q2 ) # not sure
You may instead need to use .intersection (doc here)
qs1 = Product.objects.filter( q1)
qs2 = Productr.objects.filter( q2)
results = qs1.intersection( qs2)
See also .union, .difference
At this poimt I'll admit I'm talking about things I have read about but never tried. You will have to experiment, and read the Django docs over and over again!

How to inner join tables based on ManyToManyField and group by a parameter and get latest one in Django?

I have two models with ManyToManyField relationship:
class Education(models.Model):
title = models.CharField(default=None, max_length=100)
content = models.TextField(default=None)
price = models.ManyToManyField(Price)
class Price(models.Model):
cost = models.CharField(default=None, max_length=20)
created_at = models.DateTimeField(auto_now=True, null=True, blank=True)
I can fetch all rows like this:
result = Education.objects.filter(price__in=Price.objects.all()).select_related('Price')/
.values_list('title', 'content', 'price__cost', 'price__created_at')
But now i want to group by education.id and the cost parameter should be latest parameter that inserted(based on created_at).
So i want to have list of all Education with latest cost that inserted for every education.
Will it work for you, It will return the respective id
Education.objects.filter(price__in=Price.objects.all()).select_related('Price').values('id').annotate(price_id=Max('price__id'))

Queryset of model instances based on related model

I've got two models.
class Color(models.Model):
name = models.CharField(max_length=120, null=True, blank=True)
class Car(models.Model):
user = models.ForeignKey(Color, on_delete=models.CASCADE, default=None)
price = models.DecimalField(max_digits=10, decimal_places=2)
How can I get a queryset of Color instances where the Car instances that are related to those Color instances have a price > 1000?
Thanks!
You can use something like:
related_colors = Color.objects.filter(car_set__price__gt=1000)
Assuming you meant color instead of user? You can filter it as follows:
cars = models.Car.objects.filter(price__gte = 1000).values_list('color', flat = True)

Making many-to-many relationships with different price for different customer

I have three models Product, Buyer and Offer.
Any buyer can inquire about any kind of Product but for each customer I might offer a different price.
The net price of a product is already given by the supplier.
I wrote the code below and suddenly realized I can only select products for an offersheet but cannot give a different price every time for each product and for each customer with this code.
It would be nice if anyone could give me some suggestions.
Thanks.
class Product(models.Model):
name = models.CharField(...)
net_price = models.NumericField(...)
class Buyer(models.Model):
name = models.CharField(...)
class Offer(models.Model):
date = models.DateTimeField(auto_created=True, auto_now_add=True)
buyer = models.ForeignKey(Buyer, default='',)
products = models.ManyToManyField(Product, related_name='offer',)
You can do it as following:
class Product(models.Model):
name = models.CharField(...)
class Buyer(models.Model):
name = models.CharField(...)
class Offer(models.Model):
date = models.DateTimeField(auto_created=True, auto_now_add=True)
buyer = models.ForeignKey(Buyer)
class OfferUnit(models.Model):
offer = models.ForeignKey(Offer)
product = models.ForeignKey(Product)
net_price = models.IntegerField()
OfferUnit is like one row in your bill(invoice) so you can specify different price for different buyers.

Can't figure out join statement in Django

I'm trying to figure out how to execute the following sql join statement in Django without resorting to just raw sql. Is there a way to do it?
Select * from playertable, seasontable where player.id = season.player_id
Here are my models. Just to clarify, I used abbreviated table names in the above query for clarify
class Player(models.Model):
name = models.CharField(max_length=200)
team = models.CharField(max_length=3)
position = models.CharField(max_length=3)
class PlayerSeason(models.Model):
player = models.ForeignKey(Player)
year = models.IntegerField()
games_played = models.IntegerField()
goals = models.IntegerField()
assists = models.IntegerField()
points = models.IntegerField()
plusminus = models.CharField(max_length=200)
pim = models.IntegerField()
ppg = models.IntegerField()
shg = models.IntegerField()
gwg = models.IntegerField()
otg = models.IntegerField()
shots = models.IntegerField()
shooting_percentage = models.DecimalField(max_digits=5, decimal_places=2)
toi = models.CharField(max_length=200)
sftg = models.DecimalField(max_digits=5, decimal_places=2)
face_off = models.DecimalField(max_digits=5, decimal_places=2)
How should I do this with a Django QuerySet?
If all you wanted to do was to get all the players associated with a given season you could make use of Django's backwards relationships
When you use a ForeignKeyField to a model, in this case Season, the that model instances get an attribute which allows you to get a queryset of all the related objects.
In your example you could use season.player_set.all().
You can pass an optional parameter related_name to the ForeignKeyField that allows you to change the name of the season attribute.
Is there a way to do it?
No. Django's ORM deals with one model at a time, and you are getting columns from two tables. Perform a query on either of the models and then access the appropriate field to get the related model.