Django页面点击计数器并发

时间:2011-08-29 07:07:25

标签: python django concurrency auto-increment

我是一个django新手。我正在制作一个粗略的打击计数器作为Uni网络编程课程的作业。我做了一个HitCount课程:

from django.db import models

# Create your models here.

class HitCount(models.Model):
    count = models.IntegerField()

然后我在视图文件中使用此代码:

def index(request):

    #try getting a hitcounter, if there is none, create one
    try:
        hc = HitCount.objects.get(pk=1)
    except: 
        hc = HitCount(count=0)
        hc.save()
        pass

    #get a queryset containing our counter
    hc = HitCount.objects.filter(pk=1)
    #increment its count and update it in db
    hc.update(count=F('count')+1)
    #ATM hc is a queryset, so hc.count will just return how many
    #counters are in the queryset (1). So we have to get the
    #actual counter object
    hc = HitCount.objects.get(pk=1)
    #and return its count
    return render_to_response('hitcount/index.html', {'count': hc.count})

这是我的index.html文件:

<p>{{count}}</p>

这似乎工作得很好,但我想知道:

  • 这是一种合理的方法吗?增量代码是否真的存在于视图文件中?或者我应该将它移到课堂上的方法中吗?
  • 这种并发安全还是我需要使用某种锁?部分任务是使计数器并发安全。我使用SQLite,它使用事务,所以我认为应该没事,但我可能会遗漏一些东西。

3 个答案:

答案 0 :(得分:3)

关闭主题,但你应该在try / except中捕获HitCount.DoesNotExist,因为你真的只想执行除了HitCount对象之外的代码。

如果可能,您可能需要查看类似Redis(或其他键/ val商店)的内容来执行您的点击计数器。

Redis提供了一个名为INCR的方法,该方法会自动将值增加1.这对于像这样的点击计数器来说非常快,而且是一个很好的解决方案。您需要做的就是创建一个与页面相关的密钥,然后您可以将其增加+1。

使用middleware类来跟踪页面匹配也可能更有意义。比将其添加到每个视图要容易得多。如果您需要在每个页面上显示此计数,您可以使用context processormore info)将页面的点击计数添加到上下文中。以这种方式重复代码的次数会减少。

修改

我最初错过了这是一个Uni项目,所以这可能会严重超过你所需要的工程。但是,如果您要为生产环境构建一个计数器,这就是我建议的。您仍然可以使用中间件/上下文处理器以干燥方式执行命中计数/检索。

答案 1 :(得分:2)

使用以下命令可以在python中进行锁定:

lock = Lock()
lock.acquire()
try:
    ... access shared resource
finally:
    lock.release() # release lock, no matter what

请记住,这种方法在多服务器环境中并不安全。

您还可以创建一个更具扩展性的“日志记录”解决方案,该解决方案可以跟踪每个匹配作为数据库中的行以及相关信息,然后即使在特定日期范围内也可以计算/查询。

答案 2 :(得分:0)

您可以为每个匹配创建一个新的数据库行,并调用HitCount.objects.count()来获取计数。