使用 Django Celery 添加视图计数器到对象

发布于 2024-10-14 04:20:59 字数 1420 浏览 1 评论 0原文

这并不重要,但这是此问题的后续问题。

我想记录数据库中每个对象被查看的次数。假设我们有一个包含多个实例的 Person 模型。我们希望使用 Django Celery 来记录每个实例在 Person 模型中被查看的次数,以避免等待数据库写入。

目前我正在这样做:

from celery.decorators import task

class Person(models.Model):
    name = models.CharField(max_length=50)


class Stats(models.Model):
    person = models.ForeignKey('Person', unique=True)
    @task
    def addView(self):
        se = StatEvent()
        se.save()
        self.views.add(se)

class StatEvent(models.Model):
    date = models.DateTimeField(auto_now_add=True)

然后,每次调用列出人员页面的视图时,我都会获取所有人员,并像这样更新统计信息:

person.get_stats().addView.delay(person.get_stats())

然后返回要在浏览器中显示的人员列表。我认为统计信息的更新会异步发生,但在显示页面之前有一个明显且较长的延迟,这一点可以通过在 Celery 命令窗口中为每个添加显示一个 print 语句来确认。该页面仅在最后一次统计数据更新后才会呈现。

如何确保用户不会等待数据库更新完成?

更新

我认为这可能与没有足够的工作进程来单独处理每个人有关,所以我制作了一个接受人员列表作为参数的函数,并将其用作任务被处决。因此,队列中只有一个任务:

@task(ignore_result=True)
def addViews(persons):
    for person in persons:
        stats = listing.get_stats()
        se = StatEvent()
        se.save()
        stats.views.add(se)

但是,当打印到控制台时,如下所示:

    print "adding"
    print tasks.addClicks(persons)
    print "done"

然后,“添加”和“完成”步骤之间存在明显的延迟,并且函数的返回值为 None.

Not that it matters, but this is a follow-up to this question.

I want to keep a count of how many times each object in my database has been viewed. Let's say we have a Person model, with several instances. We want to keep a counter of how many times each instance has been viewed in the Person model, using Django Celery to avoid waiting for the database writes.

At the moment I'm doing this:

from celery.decorators import task

class Person(models.Model):
    name = models.CharField(max_length=50)


class Stats(models.Model):
    person = models.ForeignKey('Person', unique=True)
    @task
    def addView(self):
        se = StatEvent()
        se.save()
        self.views.add(se)

class StatEvent(models.Model):
    date = models.DateTimeField(auto_now_add=True)

Then, every time the view is called which lists a page of persons, I get all persons, update the statistics like this:

person.get_stats().addView.delay(person.get_stats())

where after I then return the list of persons to be displayed in the browser. I thought that the updating of the statistics would happen asynchronously, but there's a clear and long delay before the page is displayed, which is confirmed by having a print statement shown for each addition in the Celery command window. The page is only rendered once the last statistic has been updated.

How do I ensure that the user doesn't wait for the database update to finish?

Update

I thought it might have something to do with there not being enough worker processes to process each person separately, so I instead made a function that accepts a list of persons as parameter, and used this as the task to be executed. So, only one task in the queue:

@task(ignore_result=True)
def addViews(persons):
    for person in persons:
        stats = listing.get_stats()
        se = StatEvent()
        se.save()
        stats.views.add(se)

However, when print to the console, like this:

    print "adding"
    print tasks.addClicks(persons)
    print "done"

Then there's a clear delay between the "adding" and "done" step, and the returned value of the function is None.

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

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

发布评论

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

评论(1

油饼 2024-10-21 04:20:59

事实证明,我最初对工人不足的怀疑是正确的。我的新函数将所有内容都放在一个任务中解决了这个问题 - 我只是在最后一个 tasks.addClicks(persons) 调用中错过了 .delay

Turns out my original suspicion about there not being enough workers was correct. My new function that put everything in one task solved the problem - I was just missing the .delay in that last tasks.addClicks(persons) call.

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