按日期间隔和重量对产品进行排序

发布于 2024-08-15 05:27:09 字数 1383 浏览 5 评论 0原文

我想要的是能够获得本周/本月/今年等最热门的产品。因此,我有一个名为 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))之后,您将如何对产品进行排序?

这种结构也不是一成不变的,所以如果您想以任何其他方式构建模型,请告诉我们!

What I want is to be able to get this weeks/this months/this years etc. hotest products. So I have a model named ProductStatistics that will log each hit and each purchase on a day-to-day basis. This is the models I have got to work with:

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)

How would you go about sorting the Products after say (hits+(purchases*2)) the latest week?

This structure isn't set in stone either, so if you would structure the models in any other way, please tell!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

兔姬 2024-08-22 05:27:09

第一个想法:

在视图中,您可以查询今天的 ProductStatistic,然后循环查询集并向每个对象添加一个变量 ranking 并将该对象添加到列表中。然后按照ranking进行排序,并将列表传递给您的模板。

第二个想法:

创建一个归档的排名(对管理员隐藏),并在每次将对象保存到数据库时使用 pre_save-signal。现在您可以执行 ProductStatistic.objects.filter(date=today()).order_by('ranking')

两种想法都有优点和缺点,但我喜欢第二个想法更多

编辑作为对评论的响应

  • < p>使用想法2

  • 编写一个视图,在其中进行如下过滤:ProductStatistic.objects.filter(product= aProductObject, date__gte=startdate, date__lte=enddate)

    循环查询集并执行诸如aProductObject.ranking+= qs_obj.ranking

    之类的操作

  • 将查询集的排序列表传递给模板

基本上是两种想法的组合

,编辑为您自己的回答

你的解决方案与我的建议相距不远 - 但在 sql-space 中。

但另一个解决方案:

创建一个命中模型:

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(product=product,
    date=datetime.datetime.now(),
    session=request.session.session_key).save()

在购买视图中,您将获得命中对象并设置 purchased=True

现在,您可以在模板/数据库工具中进行真正的统计。

当然,随着时间的推移,它会生成大量的 DB-Objects,因此您应该考虑一个好的删除策略(例如将 3 个月后的数据求和到另一个模型 MonthlyHitArchive),

如果您认为,显示此统计信息会产生大量数据库流量,您应该考虑使用一些缓存。

first idea:

in the view you could query for today's ProductStatistic, than loop over the the queryset and add a variable ranking to every object and add that object to a list. Then just sort after ranking and pass the list to ur template.

second idea:

create a filed ranking (hidden for admin) and write the solution of ur formula each time the object is saved to the database by using a pre_save-signal. Now you can do ProductStatistic.objects.filter(date=today()).order_by('ranking')

Both ideas have pros&cons, but I like second idea more

edit as response to the comment

  • Use Idea 2

  • Write a view, where you filter like this: ProductStatistic.objects.filter(product= aProductObject, date__gte=startdate, date__lte=enddate)

    loop over the queryset and do somthing like aProductObject.ranking+= qs_obj.ranking

  • pass a sorted list of the queryset to the template

Basically a combination of both ideas

edit to your own answer

Your solution isn't far away from what I suggested — but in sql-space.

But another solution:

Make a 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)

in your view for displaying a product you check, if there is a Hit-object with the session, and object. if not, you save it

Hit(product=product,
    date=datetime.datetime.now(),
    session=request.session.session_key).save()

in your purchase view you get the Hit-object and set purchased=True

Now in your templates/DB-Tools you can do real statistics.

Of course it can generate a lot of DB-Objects over the time, so you should think about a good deletion-strategy (like sum the data after 3 month into another model MonthlyHitArchive)

If you think, that displaying this statistics would generate to much DB-Traffic, you should consider using some caching.

耶耶耶 2024-08-22 05:27:09

我以我不想解决的方式解决了这个问题。我将 week_rankmonth_rankoverall_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()

如果有更好的解决方案,我将不予解决。

I solved this the way I didn't want to solve it. I added week_rank, month_rank and overall_rank to Product and then I just added the following to my ProductStatistic model.

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()

I'll leave it unsolved if there is a better solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文