Python Django对象锁定

Python Django对象锁定,python,django,multithreading,Python,Django,Multithreading,我使用的是Django 1.8,我有一个模型 class ModelA(models.Model): some_field = models.PositiveIntegerField() 现在,在我的视图中,我想添加一个新的ModelA对象,但前提是该值的条目已经少于x个 def my_view(request): # Using the value of 4 here just as an example c = ModelA.objects.filter(some_

我使用的是Django 1.8,我有一个模型

class ModelA(models.Model):
    some_field = models.PositiveIntegerField()
现在,在我的视图中,我想添加一个新的ModelA对象,但前提是该值的条目已经少于x个

def my_view(request):
    # Using the value of 4 here just as an example
    c = ModelA.objects.filter(some_field=4).count()
    # Check if fewer than (x=20) objects with this field already
    if c < 20:
        # Fewer, so create one
        new_model = ModelA(4)
        new_model.save()
    else:
        # Return a message saying "too many"
还是我应该考虑用其他方法来做这件事?只有插入,从不更新或删除


谢谢

为此,您需要锁定整个表,如何锁定取决于您使用的RDBMS。它将涉及原始sql的使用。另一种方法是在保存记录后进行计数

def my_view(request):
    new_model = ModelA(4)
    new_model.save()

    try :
        c = ModelA.objects.filter(some_field=4)[20]
        if c.pk == new_model.pk:
           c.delete()
        # Return a message saying "too many"

    except IndexError:
        pass

这种方法不会互相妨碍,每个线程负责删除它添加的额外项。如果在Django 1.10.x和postgres上测试的计数大于20,则可以使用原子和回滚,而不是删除:

models.py:

class ModelA(models.Model):
    some_field = models.PositiveIntegerField()
    active = models.BooleanField()
以及:


问自己,20是硬限制还是软限制?两个线程同时计数19然后再插入另一个线程是很少见的:结果21个对象是灾难性的,还是仅仅是一个对任何东西都没有太大伤害的奇怪现象?这是一个硬限制。视图请求可能会添加1个对象,也可能会添加4个对象。我需要知道有足够的“空间”来容纳这么多的条目。谢谢,这似乎是一种很好的、优雅的处理方式。我可能应该在原始问题中提到,视图请求可能会创建一个或多个对象,因此它需要确保有足够的“空间”来插入所有对象。我想我可以扩展你发布的想法,这样它就可以跟踪它插入的所有对象,然后检查并删除它们。当Django提供这么多现成的东西时,感觉应该有某种内置的锁定机制!Django没有提供这种开箱即用的方案,因为这是一种非常不寻常的方案,而且实现需要大量的工作,因为数据库以不同的方式处理它。它是如何工作的?它是如何工作的?但我最终决定改变我处理它的方式。相反,我向具有计数的相关对象添加了一个新字段,并在事务中更新了该字段。原子()选择\u作为\u更新方式,因为一次可以添加多个字段。不过,我会记住这一点,以备将来使用。谢谢你很好。祝你的项目一切顺利
class ModelA(models.Model):
    some_field = models.PositiveIntegerField()
    active = models.BooleanField()
from django.db.models.expressions import RawSQL

n = 42
maximum = 3

raw_sql = RawSQL('select (select count(*) from fooapp_modela where some_field=%s) < %s', (n, maximum))
while True:
    o = ModelA.objects.create(some_field=n, active=raw_sql)
    o.refresh_from_db()
    print(o.id, o.active)
    if not o.active:
        # o.delete()
        break
class ModelA(models.Model):
    some_field = models.PositiveIntegerField()
    ordinal = models.IntegerField()

    class Meta:
         unique_together = (
             ('some_field', 'ordinal'),
         )

#...

raw_sql = RawSQL('select count(*) + 1 from fooapp_modela where some_field=%s', (n,))

o = ModelA.objects.create(some_field=n, ordinal=raw_sql) # retry a few times on IntegrityError
o.refresh_from_db()
print(o.id, o.ordinal)