考虑一个通用应用程序,每次他们做好事时都会为其用户提供分数
我有模特
protected function hasInvalidState()
{
if ($this->isStateless()) {
return false;
}
$session = $this->request->getSession();
dd($session);
dd($this->request->input('state'));
return ! ($this->request->input('state') === $session->get('state'));
}
现在,每次添加新契约时,都会重新计算该用户的总分数,并且每次重新计算用户的分数时,也会重新计算所有用户(针对其他用户)的排名。
这太可怕了,我想聚合所有排名更新请求,并且每隔几分钟只执行一次。有没有python库可以做这样的事情?
cron作业是一种选择,但它会每隔几分钟更新一次所有用户的排名,无论是否需要更新。
编辑:基于@The Django Ninja的建议,我写了这个装饰并分享它class GoodDeed(models.Model):
user = models.ForgeinKey(CustomUser)
points = models.IntegerField(default=0, blank=True)
class CustomUser(models.Model):
points = models.IntegerField(default=0, blank=True)
rank = models.IntegerField(blank=True, null=True)
class CustomUser(models.Model):
@cached_model_property
def points(self):
del self.rank # removed cached rank value
return sum(self.good_deeds.values_list("points", flat=True))
@cached_model_property(readonly=False)
def rank(self):
user_list = []
for user in User.onjects.all().only("points")
user_list.push((user.points, user))
# sort the list
user_list.sort(reverse=True)
# update all ranking
rank = 0
my_rank = None
for points, user in user_list:
rank += 1
if user.pk == self.pk:
# Don't update this instance's rank yet, as it will be
# updated when the function return
my_rank = rank
continue
# Save the new rank in the cache
user.rank = rank
# If you forget to return something (not None) caching will always assumed to be invalid
return my_rank
id为20的用户的缓存排名值将存储在名为的缓存键中 'User.20.rank'
>>> user.points
# call points() method, cache the result, return it
>>> user.points
# return cached result without calling points() method
>>> del user.points
>>> user.points
# call points() method, cache the result, return it
>>> user.rank
# 1. Calculate and save (in cache) rank of all users except current user
# 2. Cache current user's rank and return it
>>> user.rank
# return cached user's rank
>>> del user.points
>>> user.rank
# Recalculate user's points and all ranking values
>>> user.points = 9
# Readonly property exception
答案 0 :(得分:2)
如上所述,排名任务似乎在数据库上做了一些重要的工作。
我会选择基本的缓存失效解决方案,如果更新了用户排名,缓存应该无效:
from django.core.cache import cache
def the_function_that_update_user_rank()
# updating the rank of the user
# when the rank is updated we set our cache key (global-rank-update-needed) to True
cache.set('global-rank-update-needed', 'True')
然后一个cron作业应该每隔x秒调用一次manage.py命令,如果'global-rank-update-needed'为True,命令将从缓存中检查,然后更新全局等级:
from django.core.cache import cache
class UpdateGlobalRank(BaseCommand):
help = 'Closes the specified poll for voting'
def handle(self, *args, **options):
if cache.get('global-rank-update-needed') == 'True':
# here do the update rank stuff
print 'Updating the Global Rank'
cache.set('global-rank-update-needed', 'False')
遵循此方法,只有在某些用户的排名发生变化时才会更新全局排名
希望它有所帮助。
答案 1 :(得分:0)
我更喜欢celery
这类任务。
是一个任务队列,专注于实时处理,同时还支持任务调度