相关疑难解决方法(0)

Django的原子操作?

我正在尝试实现(我认为)一个非常简单的计数器数据模型:

class VisitorDayTypeCounter(models.Model):
    visitType = models.CharField(max_length=60)
    visitDate = models.DateField('Visit Date')
    counter = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)

当有人通过时,它将查找与visitType和visitDate匹配的行; 如果此行不存在,则将使用counter = 0创建.

然后我们增加计数器并保存.

我担心的是这个过程完全是一场竞赛.两个请求可以同时检查实体是否存在,并且它们都可以创建它.在读取计数器并保存结果之间,另一个请求可能会通过并递增(导致计数丢失).

到目前为止,我还没有找到一个很好的方法,无论是在Django文档还是在教程中(实际上,看起来教程在投票部分有竞争条件).

我该如何安全地做到这一点?

database django concurrency locking race-condition

24
推荐指数
5
解决办法
8181
查看次数

django是否存在防止重复表单提交的库?

我试图找到一种方法来阻止用户双重提交我的表单.我有javascript禁用提交按钮,但仍然有偶尔的用户找到双重提交的方法.

我有一个可重用的库的愿景,我可以创建以防止这种情况.

在我理想的库中,代码块看起来像这样:

try:
    with acquire_lock({'field1':'abc', 'field2':'def'}) as lock:
        response = #do some credit card processing
        lock.response = response
except SubmissionWasDuplicate, e:
    response = e.response
Run Code Online (Sandbox Code Playgroud)

锁表看起来像这样:

duplicate_submission_locks

  • submission_hash#提交参数的MD5
  • 响应#腌制数据
  • created_at#用于扫描此表
  • lock_expired #boolean表示锁是否已过期

有谁知道这是否已经存在?它似乎并不难写,所以如果它不存在我可以自己写.

python django code-reuse

18
推荐指数
2
解决办法
6371
查看次数

Django模型中的并发控制

如何在Django模型中处理并发?我不希望记录的更改被另一个读取相同记录的用户覆盖.

python django concurrency django-models

17
推荐指数
3
解决办法
1万
查看次数

如何在Django中完成文本的完整历史记录?

我想拥有用户编辑的大文本字段的完整历史记录,使用Django存储.

我见过这些项目:

我有一个特殊的用例,可能超出了这些项目提供的范围.此外,我对这些项目的文档记录,测试和更新情况保持警惕.无论如何,这是我面临的问题:

我有一个模特,喜欢:

from django.db import models

class Document(models.Model):
   text_field = models.TextField()
Run Code Online (Sandbox Code Playgroud)

这个文本字段可能很大 - 超过40k - 我希望有一个自动保存功能,每30秒左右保存一次字段.这可能会使数据库变得非常大,显然,如果每次40k都有很多保存(如果压缩可能仍然是10k).我能想到的最佳解决方案是保持最新保存版本和新版本之间的差异.

但是,我担心涉及并行更新的竞争条件.有两种截然不同的竞争条件(第二种情况比第一种情况严重得多):

  1. HTTP事务竞争条件:用户A和用户B请求文档X0,并单独进行更改,生成Xa和Xb.Xa被保存,X0和Xa之间的差异是"Xa-0"("少了一点"),Xa现在被存储为数据库中的正式版本.如果Xb随后保存,则覆盖Xa,差异为Xb-a("b减去a").

    虽然不理想,但我并不过分担心这种行为.文档相互重写,用户A和B可能彼此不知道(每个文档都以文档X0开头),但历史保留了完整性.

  2. 数据库读取/更新竞争条件:有问题的竞争条件是Xa和Xb同时保存在X0上.会有(伪)代码类似于:

     def save_history(orig_doc, new_doc):
         text_field_diff = diff(orig_doc.text_field, new_doc.text_field)
         save_diff(text_field_diff)
    
    Run Code Online (Sandbox Code Playgroud)

    如果Xa和Xb都从数据库中读取X0(即orig_doc是X0),它们的差异将变为Xa-0和Xb-0(与序列化的Xa-0相反,然后是Xb-a,或等效的Xb-0然后Xa b).当您尝试将差异拼接在一起以生成历史记录时,它将在修补程序Xa-0或Xb-0(均适用于X0)上失败.历史的完整性已经受到损害(或者有吗?).

    一种可能的解决方案是自动协调算法,该算法可以事后检测这些问题.如果重建历史记录失败,可能会假设已发生竞争条件,因此将失败的修补程序应用于历史记录的先前版本,直到成功为止.

我很高兴能就如何解决这个问题得到一些反馈和建议.

顺便说一句,只要它是一个有用的出路,我注意到这里讨论了Django原子性:

非常感谢你.

django parallel-processing concurrency atomic django-models

9
推荐指数
1
解决办法
2582
查看次数

Django 中的并发请求

我有 2 个模型:ProductOrder.

Product有一个股票的整数字段,而Order有一个状态和一个外键Product

class Product(models.Model):
    name = models.CharField(max_length=30)
    stock = models.PositiveSmallIntegerField(default=1)

class Order(models.Model):
    product = models.ForeignKey('Product')
    DRAFT = 'DR'; INPROGRESS = 'PR'; ABORTED = 'AB'
    STATUS = ((INPROGRESS, 'In progress'),(ABORTED, 'Aborted'),)
    status = models.CharField(max_length = 2, choices = STATUS, default = DRAFT)
Run Code Online (Sandbox Code Playgroud)

我的目标是让每个新订单的产品库存减少一个,每个订单取消增加一个。为此,我重载了模型的save方法Order(受Django启发:保存时,如何检查字段是否已更改?):

from django.db.models import F

class Order(models.Model):
    product = models.ForeignKey('Product')
    status = models.CharField(max_length = 2, choices = STATUS, default …
Run Code Online (Sandbox Code Playgroud)

django postgresql transactions django-rest-framework

4
推荐指数
1
解决办法
7487
查看次数

你如何在Python/Django/MySQL中避免这种竞争条件?

我有一个模型MyModel,它有一个字段expiration_datetime.

每次用户检索MyModel的实例时,我都需要先检查它是否已过期.如果它已经过期,我需要增加一些计数器,更新其他计数器,然后将expiration_datetime扩展到将来的某个时间.

所以视图会做类似的事情:

if object.expiration_datetime < datetime.datetime.now(): 
    object.counter = F('counter') + 1 
    object.expiration_datetime = F('expiration_datetime') + datetime.timedelta(days=1) 
    object.save() 
Run Code Online (Sandbox Code Playgroud)

上面的代码中存在竞争条件.假设线程1检查并发现当前实例已过期,它继续增加计数器并延长到期日期时间.但是在它可以这样做之前,线程2被安排并且做同样的事情.到线程1最终完成时,计数器已递增两次,expration_datetime已延长两次.

这看起来应该是一个非常常见的问题.处理它的最有效方法是什么?理想情况下,我希望能够以数据库可移植的方式在Django中处理它.

python mysql database django race-condition

3
推荐指数
1
解决办法
4364
查看次数