我想要的是能够获得本周/本月/今年等最热门的产品。所以我有一个名为ProductStatistics
的模型,它会记录每次点击和每次购买的日常工作。这是我必须使用的模型:
class Product(models.Model):
name = models.CharField(_("Name"), max_length=200)
slug = models.SlugField()
description = models.TextField(_("Description"))
picture = models.ImageField(upload_to=product_upload_path, blank=True)
category = models.ForeignKey(ProductCategory)
prices = models.ManyToManyField(Store, through='Pricing')
objects = ProductManager()
class Meta:
ordering = ('name', )
def __unicode__(self):
return self.name
class ProductStatistic(models.Model):
# There is only 1 `date` each day. `date` is
# set by datetime.today().date()
date = models.DateTimeField(default=datetime.now)
hits = models.PositiveIntegerField(default=0)
purchases = models.PositiveIntegerField(default=0)
product = models.ForeignKey(Product)
class Meta:
ordering = ('product', 'date', 'purchases', 'hits', )
def __unicode__(self):
return u'%s: %s - %s hits, %s purchases' % (self.product.name, str(self.date).split(' ')[0], self.hits, self.purchases)
在最近一周(hits+(purchases*2))
之后,您将如何对产品进行分类?
这个结构也不是一成不变的,所以如果你以其他方式构建模型,请告诉我们!
答案 0 :(得分:1)
在视图中,您可以查询今天的ProductStatistic
,而不是遍历查询集并向每个对象添加变量ranking
并将该对象添加到列表中。然后只需在ranking
之后排序并将列表传递给您的模板。
创建一个字段ranking
(对管理员隐藏),并在每次使用pre_save-signal将对象保存到数据库时编写ur公式的解决方案。现在你可以做ProductStatistic.objects.filter(date=today()).order_by('ranking')
这两个想法都有优点和缺点,但我更喜欢第二个想法
使用Idea 2
写一个视图,按照这样过滤:ProductStatistic.objects.filter(product= aProductObject, date__gte=startdate, date__lte=enddate)
遍历查询集并执行aProductObject.ranking+= qs_obj.ranking
将查询集的已排序列表传递给模板
基本上是两种想法的组合
你的解决方案离我的建议不远 - 但是在sql-space中。
但另一种解决方案:
制作一个Hit-Model:
class Hit(models.Model):
date = models.DateTimeFiles(auto_now=True)
product = models.ForeignKey(Product)
purchased= models.BooleanField(default=False)
session = models.CharField(max_length=40)
在您的视图中显示您检查的产品,是否存在包含会话的Hit对象和对象。如果没有,你保存它
Hit(product=product,
date=datetime.datetime.now(),
session=request.session.session_key).save()
在您的购买视图中,您获得了Hit-object并设置了purchased=True
现在,您可以在模板/数据库工具中进行实际统计。
当然它可以随时生成大量的数据库对象,所以你应该考虑一个好的删除策略(比如在3个月之后将数据加到另一个模型中MonthlyHitArchive
)
如果您认为显示此统计信息会产生大量数据库流量,您应该考虑使用一些缓存。
答案 1 :(得分:0)
我解决了这个问题,我不想解决它。我已将week_rank
,month_rank
和overall_rank
添加到Product
,然后我将以下内容添加到ProductStatistic
模型中。
def calculate_rank(self, days_ago=7, overall=False):
if overall:
return self._default_manager.all().extra(
select = {'rank': 'SUM(hits + (clicks * 2))'}
).values()[0]['rank']
else:
return self._default_manager.filter(
date__gte = datetime.today()-timedelta(days_ago),
date__lte = datetime.today()
).extra(
select = {'rank': 'SUM(hits + (clicks * 2))'}
).values()[0]['rank']
def save(self, *args, **kwargs):
super(ProductStatistic, self).save(*args, **kwargs)
t = Product.objects.get(pk=self.product.id)
t.week_rank = self.calculate_rank()
t.month_rank = self.calculate_rank(30)
t.overall_rank = self.calculate_rank(overall=True)
t.save()
如果有更好的解决方案,我会解决它。