Min*_*ana 5 sql django postgresql django-models django-queryset
我有4个这样的模特
class Site(models.Model):
name = models.CharField(max_length=200)
def get_lowest_price(self, mm_date):
'''This method returns lowest product price on a site at a particular date'''
class Category(models.Model):
name = models.CharField(max_length=200)
site = models.ForeignKey(Site)
class Product(models.Model):
name = models.CharField(max_length=200)
category = models.ForeignKey(Category)
class Price(models.Model):
date = models.DateField()
price = models.IntegerField()
product = models.ForeignKey(Product)
Run Code Online (Sandbox Code Playgroud)
这里每个都有很多类别,每个类别都有很多产品.现在产品价格每天都在变化,所以价格型号将保持产品价格和日期.
我的问题是我想按价格范围过滤网站过滤器列表.此价格范围取决于get_lowest_price方法,可以是Min to Max和Max to Min.我已经使用lambda表达式来做到这一点,但我认为这是不合适的
sorted(Site.objects.all(), key=lambda x: x.get_lowest_price(the_date))
Run Code Online (Sandbox Code Playgroud)
此外,我可以通过运行循环获得价格范围内的所有网站,但这也不是一个好主意.请帮助我的人以正确的方式进行查询.
如果您仍然需要更清晰的问题视图,请参阅"Ishtiaque Khan"的第一条评论,他的假设是100%正确的.
*在这些型号中,写入频率低且读取频率高.
1. 使用查询
如果您只想使用特定日期进行查询。具体方法如下:
q = Site.objects.filter(category__product__price__date=mm_date) \
.annotate(min_price=Min('category__product__price__price')) \
.filter(min_price__gte=min_price, min_price__lte=max_price)
Run Code Online (Sandbox Code Playgroud)
它将返回-mm_date
范围内价格最低的网站列表。您还可以使用如下查询来查询多个日期:min_price
max_price
q = Site.objects.values('name', 'category__product__price__date') \
.annotate(min_price=Min('category__product__price__price')) \
.filter(min_price__gte=min_price, min_price__lte=max_price)
Run Code Online (Sandbox Code Playgroud)
2. 渴望/预先计算,可以使用post_save
信号。由于写入频率较低,因此不会很昂贵
class LowestPrice(models.Model):
date = models.DateField()
site = models.ForeignKey(Site)
lowest_price = models.IntegerField(default=0)
Run Code Online (Sandbox Code Playgroud)
post_save
每次都使用信号来计算和更新它。示例代码(未测试) from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Price)
def update_price(sender, instance, **kwargs):
cur_price = LowestPrice.objects.filter(site=instance.product.category.site, date=instance.date).first()
if not cur_price:
new_price = LowestPrice()
new_price.site = instance.product.category.site
new_price.date = instance.date
else:
new_price = cur_price
# update price only if needed
if instance.price<new_price.lowest_price:
new_price.lowest_price = instance.price
new_price.save()
Run Code Online (Sandbox Code Playgroud)
LowestPrice.objects.filter(date=mm_date, lowest_price__gte=min_price, lowest_price__lte=max_price)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1119 次 |
最近记录: |