Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Filter Model One-To-Many relation, greatest diff between prices

I have a product model with a foreign key to some prices, and I really want to list the products with the "best" offer... How to do that?

class Product(models.Model):
    productname = models.CharField(max_length=1024)

class Price(models.Model):
    product = models.ForeignKey(Product)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    created = models.DateTimeField(auto_now_add=True)

First I want all products with more than one price, that I got:

ps = Product.objects.annotate(c=Count("price")).filter(c__gt=2)

Now i want the best 6 products with the largest diff between the two latest prices.

Can anyone help with that? I hope it makes sense ;)

like image 757
pkdkk Avatar asked Jan 26 '14 00:01

pkdkk


People also ask

What is the purpose of filter () method in Django?

The filter() method is used to filter you search, and allows you to return only the rows that matches the search term.

What is the difference between filter and get method in Django?

Returns a new QuerySet containing objects that match the given lookup parameters. Basically use get() when you want to get a single unique object, and filter() when you want to get all objects that match your lookup parameters.

What is Q filter Django?

Q object encapsulates a SQL expression in a Python object that can be used in database-related operations. Using Q objects we can make complex queries with less and simple code. For example, this Q object filters whether the question starts wiht 'what': from django. db.

What is all () in Django?

The method all() on a manager just delegates to get_queryset() , as you can see in the Django source code: def all(self): return self.get_queryset() So it's just a way to get the QuerySet from the Manager. This can be handy to ensure that you're dealing with a QuerySet and not a Manager, because MyModel.


2 Answers

You can use the StdDev (Standard Deviation) aggregator, so your queryset could look like this:

ps = Product.objects.filter(price__gt=1).annotate(dev=StdDev("price__price"), min_price=Min("price__price")).order_by('-dev')[:6]

the best offer price is ps[0].min_price

Hope this helps

like image 176
juliocesar Avatar answered Sep 28 '22 01:09

juliocesar


Simple way - use predefined field

class Product(models.Model):
    productname = models.CharField(max_length=1024)
    price_diff = models.DecimalField(max_digits=10, decimal_places=2, default=0)

use signals or override save and delete :

class Price(models.Model):
    product = models.ForeignKey(Product)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    created = models.DateTimeField(auto_now_add=True)
    def save(self, **kwargs):
         ...
         #calaculate you largest diff and put in product
         ...
like image 40
vadimchin Avatar answered Sep 27 '22 23:09

vadimchin