开发者

Adding a view counter to objects using Django Celery

开发者 https://www.devze.com 2023-02-06 12:46 出处:网络
Not that it matters, but this is a follow-up to this question. 开发者_C百科 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, wit

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

开发者_C百科

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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消