首页 > 解决方案 > 在 django 中计算每天的对象访问次数

问题描述

我有一个像下面这样的模型

class Watched(Stamping):
    user = models.ForeignKey("User", null=True, blank=True, on_delete=models.CASCADE,
                             default=None)
    count = models.PositiveIntegerField()

每次查看对象时,count 属性都会增加 1。

我的问题是如何找到一个物体每天被击中的次数。我怎样才能做到这一点。

Stamping是另一种型号,带有created_atupdated_at

标签: django

解决方案


考虑在模型本身或模型的管理器中添加自定义方法。在这里,我添加了一个自定义方法visit(),该方法在检索目标对象时也会增加它们的计数。

  • 这应该优先于覆盖现有方法的选项,例如filter()并且get()不影响那些默认功能。自定义方法可以显式用于检索计数中具有更新的对象。
from django.db import models


class WatchedManager(models.Manager):
    def visit(self, *args, **kwargs):  # Behaves like QuerySet.filter()
        qs = self.get_queryset().filter(*args, **kwargs)
        qs.update(count=models.F('count') + 1)
        return qs


class Watched(models.Model):
    objects = WatchedManager()

    user = models.CharField(max_length=200)
    count = models.PositiveIntegerField()

首先,让我们列出所有对象

$ python3 manage.py shell
>>> from my_app.models import Watched
>>> 
>>> Watched.objects.all()
<QuerySet [<Watched: Watched object (1)>, <Watched: Watched object (2)>, <Watched: Watched object (3)>, <Watched: Watched object (4)>, <Watched: Watched object (5)>, <Watched: Watched object (6)>]>
>>> Watched.objects.values()
<QuerySet [{'id': 1, 'user': 'One', 'count': 0}, {'id': 2, 'user': 'Two', 'count': 0}, {'id': 3, 'user': 'Three', 'count': 0}, {'id': 4, 'user': 'Four', 'count': 0}, {'id': 5, 'user': 'Five', 'count': 0}, {'id': 6, 'user': 'Six', 'count': 0}]>

我们有 6 个对象命名为 from"One""Six",所有对象的初始计数为0。现在让我们尝试访问以 、和结尾"e"的名称。"One""Three""Five"

>>> result = Watched.objects.visit(user__endswith='e')
>>> result
<QuerySet [<Watched: Watched object (1)>, <Watched: Watched object (3)>, <Watched: Watched object (5)>]>
>>> result.values()
<QuerySet [{'id': 1, 'user': 'One', 'count': 1}, {'id': 3, 'user': 'Three', 'count': 1}, {'id': 5, 'user': 'Five', 'count': 1}]>
>>> Watched.objects.values()
<QuerySet [{'id': 1, 'user': 'One', 'count': 1}, {'id': 2, 'user': 'Two', 'count': 0}, {'id': 3, 'user': 'Three', 'count': 1}, {'id': 4, 'user': 'Four', 'count': 0}, {'id': 5, 'user': 'Five', 'count': 1}, {'id': 6, 'user': 'Six', 'count': 0}]>

您可能会注意到,它们的所有计数都自动增加 1,而其余的仍然是0。现在让我们尝试访问以 is 和 开头"T""Two"名称"Three"

>>> result = Watched.objects.visit(user__startswith='T')
>>> result
<QuerySet [<Watched: Watched object (2)>, <Watched: Watched object (3)>]>
>>> result.values()
<QuerySet [{'id': 2, 'user': 'Two', 'count': 1}, {'id': 3, 'user': 'Three', 'count': 2}]>
>>> Watched.objects.values()
<QuerySet [{'id': 1, 'user': 'One', 'count': 1}, {'id': 2, 'user': 'Two', 'count': 1}, {'id': 3, 'user': 'Three', 'count': 2}, {'id': 4, 'user': 'Four', 'count': 0}, {'id': 5, 'user': 'Five', 'count': 1}, {'id': 6, 'user': 'Six', 'count': 0}]>

您可能会注意到,两条记录都增加了 1,因此"Three"现在2在增加两次之后的计数为 。

请注意,您想要对 HTTP GET 请求执行的操作(此处通过方法实现)的副作用WatchedManager.visit()意味着数据库(特别是字段)中将会有更新Watched.count,这可以被视为反模式因为 HTTP GET 请求是为了不执行更新。


推荐阅读