在数据库中递增 IntegerField 计数器

Posted

技术标签:

【中文标题】在数据库中递增 IntegerField 计数器【英文标题】:Incrementing IntegerField counter in a database 【发布时间】:2016-10-23 03:13:09 【问题描述】:

作为 Django 的初学者,我尝试制作一个简单的应用程序,该应用程序可以通过 Http 响应查看内容的次数。 我创建了一个新的Counter 模型,并在里面添加了 IntegerField 模型count

class Counter(models.Model):
    count = models.IntegerField(default=0)
    def __int__(self):
        return count

在视图中,我从Counter() 类中创建了一个变量counter,并尝试将+1 添加到counter.count 整数,但是当我尝试保存时,它会给我一个整数不能为的错误已保存。

所以我尝试保存课程:

def IndexView(response):
    counter = Counter()
    counter.count = counter.count + 1
    counter.save()
    return HttpResponse(counter.count)

这个方法,会一直显示1,重载后无法改变。


如何正确更改IntegerField 模型,以便在每次查看后更新它,并且即使重新加载服务器也会保存?

【问题讨论】:

每次执行Counter() 时,都会在数据库中创建一个新对象,其中count 字段的值将为0,并且将其加一。您需要再次获取相同的对象。 【参考方案1】:

问题

是的,但是您正在为每个请求创建一个新的 Counter 对象,该对象又从 0 开始,这是您的问题

def IndexView(response):
    counter = Counter() # This creates a new counter each time
    counter.count = counter.count + 1
    counter.save()
    return HttpResponse(counter.count)

您在上面所做的操作会导致数据库中有一堆带有count = 1 的 Counter 对象。

解决方案

下面的示例向您展示了如何使用 get_or_create() 获取现有的 Counter 对象并将其递增或创建它(如果它不存在)

首先我们需要将一个 Counter 关联到例如一个页面(或任何东西,但我们需要某种方式来识别它并从数据库中获取它)

class Counter(models.Model):
    count = models.IntegerField(default=0)
    page = models.IntegerField() # or any other way to identify
                                 # what this counter belongs to

然后:

def IndexView(response):
    # Get an existing page counter, or create one if not found (first page hit)
    # Example below is for page 1

    counter, created = Counter.objects.get_or_create(page=1) 

    counter.count = counter.count + 1
    counter.save()
    return HttpResponse(counter.count)

避免count = count + 1 可能发生的竞争条件

为了避免竞争条件,请使用F expression

# When you have many requests coming in,
# this may have outdated value of counter.count:
# counter.count = counter.count + 1

# Using an F expression makes the +1 happen on the database
from django.db.models import F
counter.count = F('count') + 1

【讨论】:

非常感谢,有没有其他方法可以改变 IntegerField? 这不是问题,您已经更改了IntegerField,只是在每次默认以count = 0 开头的新对象(数据库行)上。您所做的是在数据库中产生了一堆带有count = 1 的 Counter 对象。我的示例向您展示了如何使用get_or_create() 获取现有的 Counter 对象并对其进行递增或创建它(如果它不存在)

以上是关于在数据库中递增 IntegerField 计数器的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C中的引用计数

如何通过读取、递增和更新数据库中的列来有效地保持计数

在核心数据中设置一个自动递增的字段

基于具有序列的条件递增计数器

在带有文本标签的按钮(JQuery)中递增计数器[重复]

if控制器+循环控制器+计数器,控制接口分支