gpt4 book ai didi

Django QuerySet update_or_create 创建重复条目

转载 作者:行者123 更新时间:2023-12-02 20:03:21 28 4
gpt4 key购买 nike

最近我在 update_or_create 中遇到问题方法。我先给大家一个完整的解释。

型号:

class TransactionPageVisits(models.Model):
transactionid = models.ForeignKey(
Transaction,
on_delete=models.CASCADE,
db_column='transactionid',
)
sessionid = models.CharField(max_length=40, db_index=True)
ip_address = models.CharField(max_length=39, editable=False)
user_agent = models.TextField(null=True, editable=False)
page = models.CharField(max_length=100, null=True, db_index=True)
method = models.CharField(max_length=20, null=True)
url = models.TextField(null=False, editable=False)
created_dtm = models.DateTimeField(auto_now_add=True)

class Meta(object):
ordering = ('created_dtm',)

功能:

def _tracking(self, request, response, **kwargs):
txn_details = kwargs.get('txn_details')
data = {
'sessionid': request.session.session_key,
'ip_address': get_ip_address(request),
'user_agent': get_user_agent(request),
'method': request.method,
'url': request.build_absolute_uri(),
'transactionid': txn_details.txn_object,
'page': kwargs.get('page')
}

# Keep updating/creating tracking data to model
obj, created = TransactionPageVisits.objects.update_or_create(**data)

注释:

我知道我没有向 update_or_create() 传递任何 defaults 参数,因为在编写代码时不需要(仅当所有列都为每个数据都是唯一的)。另外 _tracking() 位于中间件中,将在每个请求和响应中调用。

一切都很顺利,直到今天我遇到了以下异常:

File "trackit.py", line 65, in _tracking
obj, created = TransactionPageVisits.objects.update_or_create(**data)
File "/usr/local/lib/python2.7/dist-packages/Django-1.10.4-py2.7.egg/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.10.4-py2.7.egg/django/db/models/query.py", line 488, in update_or_create
obj = self.get(**lookup)
File "/usr/local/lib/python2.7/dist-packages/Django-1.10.4-py2.7.egg/django/db/models/query.py", line 389, in get
(self.model._meta.object_name, num)
MultipleObjectsReturned: get() returned more than one TransactionPageVisits -- it returned 2!

我注意到表中创建了两个具有完全相同值的条目(除了created_dtm,因为它具有auto_add_now=True):

| id    | sessionid                        | ip_address     | user_agent                                                                     | page | method | url                                                                                                    | created_dtm                | transactionid |
| 32858 | nrq2vwxbtsjp8yoibotpsur0zit5jhoq | xx.xxx.xxx.xxx | Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0 | | GET | https://www.example.com/example_url/?jobid=5a9f2acb4cedfd00011c7d5d&transactionid=XXXXXXXXXXXX | 2018-03-06 23:57:00.061280 | XXXXXXXXXXXX |
| 32859 | nrq2vwxbtsjp8yoibotpsur0zit5jhoq | xx.xxx.xxx.xxx | Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0 | | GET | https://www.example.com/example_url/?jobid=5a9f2acb4cedfd00011c7d5d&transactionid=XXXXXXXXXXXX | 2018-03-06 23:57:00.062121 | XXXXXXXXXXXX |

为什么首先在表中创建重复条目?

最佳答案

update_or_create 容易出现竞争条件,如 documentation 中所述。 :

As described above in get_or_create(), this method is prone to a race-condition which can result in multiple rows being inserted simultaneously if uniqueness is not enforced at the database level.

您可以在模型中使用unique_together,如另一个答案中的建议。我从未测试过这个,但显然 Django catches the IntegrityError caused by these race conditions .

关于Django QuerySet update_or_create 创建重复条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49152227/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com