django update_or_create 得到 "duplicate key value violates unique constraint "
django update_or_create gets "duplicate key value violates unique constraint "
也许我误解了 Django 的 update_or_create 模型方法的目的。
这是我的模型:
from django.db import models
import datetime
from vc.models import Cluster
class Vmt(models.Model):
added = models.DateField(default=datetime.date.today, blank=True, null=True)
creation_time = models.TextField(blank=True, null=True)
current_pm_active = models.TextField(blank=True, null=True)
current_pm_total = models.TextField(blank=True, null=True)
... more simple fields ...
cluster = models.ForeignKey(Cluster, null=True)
class Meta:
unique_together = (("cluster", "added"),)
这是我的测试:
from django.test import TestCase
from .models import *
from vc.models import Cluster
from django.db import transaction
# Create your tests here.
class VmtModelTests(TestCase):
def test_insert_into_VmtModel(self):
count = Vmt.objects.count()
self.assertEqual(count, 0)
# create a Cluster
c = Cluster.objects.create(name='test-cluster')
Vmt.objects.create(
cluster=c,
creation_time='test creaetion time',
current_pm_active=5,
current_pm_total=5,
... more simple fields ...
)
count = Vmt.objects.count()
self.assertEqual(count, 1)
self.assertEqual('5', c.vmt_set.all()[0].current_pm_active)
# let's test that we cannot add that same record again
try:
with transaction.atomic():
Vmt.objects.create(
cluster=c,
creation_time='test creaetion time',
current_pm_active=5,
current_pm_total=5,
... more simple fields ...
)
self.fail(msg="Should violated integrity constraint!")
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(ex).__name__, ex.args)
self.assertEqual("An exception of type IntegrityError occurred.", message[:45])
Vmt.objects.update_or_create(
cluster=c,
creation_time='test creaetion time',
# notice we are updating current_pm_active to 6
current_pm_active=6,
current_pm_total=5,
... more simple fields ...
)
count = Vmt.objects.count()
self.assertEqual(count, 1)
在最后一个 update_or_create 调用中我得到了这个错误:
IntegrityError: duplicate key value violates unique constraint "vmt_vmt_cluster_id_added_c2052322_uniq"
DETAIL: Key (cluster_id, added)=(1, 2018-06-18) already exists.
为什么模型没有更新?为什么 Django 尝试创建一条违反唯一约束的新记录?
你应该分开你的领域:
- 应搜索的字段
- 应更新的字段
例如:
如果我有型号:
class User(models.Model):
username = models.CharField(max_length=200)
nickname = models.CharField(max_length=200)
我想搜索用户名 = 'Nikolas' 并将此实例昵称更新为 'Nik'(如果没有用户名 'Nikolas' 我需要创建它)我应该写这个代码:
User.objects.update_or_create(
username='Nikolas',
defaults={'nickname': 'Nik'},
)
参见https://docs.djangoproject.com/en/3.1/ref/models/querysets/
update_or_create(defaults=None, **kwargs
) 基本上有两部分:
**kwargs
指定“filter”标准以确定此类对象是否已经存在;和
defaults
这是一个字典,其中包含映射到我们 创建 新行时应该使用的值的字段(以防过滤找不到一行),或者应该更新哪些值(以防我们找到这样的行)。
这里的问题是您使 过滤器 过于严格:您添加了多个过滤器,结果数据库找不到这样的行。那么会发生什么?然后数据库旨在创建具有这些过滤值的行(并且由于缺少 defaults
,因此不会添加额外的值)。但事实证明我们创建了一行,并且 cluster
和 added
的组合已经存在。因此数据库拒绝添加这一行。
所以这一行:
Model.objects.update_or_create(field1=val1,
field2=val2,
defaults={
'field3': val3,
'field4': val4
})
在语义上约等于:
try:
item = Model.objects.get(field1=val1, field2=val2)
except Model.DoesNotExist:
Model.objects.create(field1=val1, field2=val2, field3=val3, field4=val4)
else:
item = Model.objects.filter(
field1=val1,
field2=val2,
).update(
field3 = val3
field4 = val4
)
(但原始调用通常在 单个 查询中完成)。
你可能应该这样写:
Vmt.objects.update_or_create(
cluster=c,
creation_time='test creaetion time',
defaults = {
'current_pm_active': 6,
'current_pm_total': 5,
}
)
(或类似的东西)
上面已经回答的很好
为了更清楚,update_or_create() 方法应该将 **kwargs 作为您要通过过滤检查该数据是否已存在于数据库中的参数。
select some_column 来自 table_name 其中 column1='' 和 column2='';
按 **kwargs 过滤将为您提供对象。现在,如果您希望更新这些过滤对象中的任何 data/column,您应该将它们传递给 update_or_create() 方法中的默认参数。
假设您找到了一个基于过滤器的对象,现在应该选择和更新默认参数值。
如果没有根据过滤器找到匹配的对象,那么它将继续并创建一个带有过滤器的条目并传递默认参数。
也许我误解了 Django 的 update_or_create 模型方法的目的。
这是我的模型:
from django.db import models
import datetime
from vc.models import Cluster
class Vmt(models.Model):
added = models.DateField(default=datetime.date.today, blank=True, null=True)
creation_time = models.TextField(blank=True, null=True)
current_pm_active = models.TextField(blank=True, null=True)
current_pm_total = models.TextField(blank=True, null=True)
... more simple fields ...
cluster = models.ForeignKey(Cluster, null=True)
class Meta:
unique_together = (("cluster", "added"),)
这是我的测试:
from django.test import TestCase
from .models import *
from vc.models import Cluster
from django.db import transaction
# Create your tests here.
class VmtModelTests(TestCase):
def test_insert_into_VmtModel(self):
count = Vmt.objects.count()
self.assertEqual(count, 0)
# create a Cluster
c = Cluster.objects.create(name='test-cluster')
Vmt.objects.create(
cluster=c,
creation_time='test creaetion time',
current_pm_active=5,
current_pm_total=5,
... more simple fields ...
)
count = Vmt.objects.count()
self.assertEqual(count, 1)
self.assertEqual('5', c.vmt_set.all()[0].current_pm_active)
# let's test that we cannot add that same record again
try:
with transaction.atomic():
Vmt.objects.create(
cluster=c,
creation_time='test creaetion time',
current_pm_active=5,
current_pm_total=5,
... more simple fields ...
)
self.fail(msg="Should violated integrity constraint!")
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(ex).__name__, ex.args)
self.assertEqual("An exception of type IntegrityError occurred.", message[:45])
Vmt.objects.update_or_create(
cluster=c,
creation_time='test creaetion time',
# notice we are updating current_pm_active to 6
current_pm_active=6,
current_pm_total=5,
... more simple fields ...
)
count = Vmt.objects.count()
self.assertEqual(count, 1)
在最后一个 update_or_create 调用中我得到了这个错误:
IntegrityError: duplicate key value violates unique constraint "vmt_vmt_cluster_id_added_c2052322_uniq"
DETAIL: Key (cluster_id, added)=(1, 2018-06-18) already exists.
为什么模型没有更新?为什么 Django 尝试创建一条违反唯一约束的新记录?
你应该分开你的领域:
- 应搜索的字段
- 应更新的字段
例如: 如果我有型号:
class User(models.Model):
username = models.CharField(max_length=200)
nickname = models.CharField(max_length=200)
我想搜索用户名 = 'Nikolas' 并将此实例昵称更新为 'Nik'(如果没有用户名 'Nikolas' 我需要创建它)我应该写这个代码:
User.objects.update_or_create(
username='Nikolas',
defaults={'nickname': 'Nik'},
)
参见https://docs.djangoproject.com/en/3.1/ref/models/querysets/
update_or_create(defaults=None, **kwargs
) 基本上有两部分:
**kwargs
指定“filter”标准以确定此类对象是否已经存在;和defaults
这是一个字典,其中包含映射到我们 创建 新行时应该使用的值的字段(以防过滤找不到一行),或者应该更新哪些值(以防我们找到这样的行)。
这里的问题是您使 过滤器 过于严格:您添加了多个过滤器,结果数据库找不到这样的行。那么会发生什么?然后数据库旨在创建具有这些过滤值的行(并且由于缺少 defaults
,因此不会添加额外的值)。但事实证明我们创建了一行,并且 cluster
和 added
的组合已经存在。因此数据库拒绝添加这一行。
所以这一行:
Model.objects.update_or_create(field1=val1,
field2=val2,
defaults={
'field3': val3,
'field4': val4
})
在语义上约等于:
try:
item = Model.objects.get(field1=val1, field2=val2)
except Model.DoesNotExist:
Model.objects.create(field1=val1, field2=val2, field3=val3, field4=val4)
else:
item = Model.objects.filter(
field1=val1,
field2=val2,
).update(
field3 = val3
field4 = val4
)
(但原始调用通常在 单个 查询中完成)。
你可能应该这样写:
Vmt.objects.update_or_create(
cluster=c,
creation_time='test creaetion time',
defaults = {
'current_pm_active': 6,
'current_pm_total': 5,
}
)
(或类似的东西)
上面已经回答的很好
为了更清楚,update_or_create() 方法应该将 **kwargs 作为您要通过过滤检查该数据是否已存在于数据库中的参数。
select some_column 来自 table_name 其中 column1='' 和 column2='';
按 **kwargs 过滤将为您提供对象。现在,如果您希望更新这些过滤对象中的任何 data/column,您应该将它们传递给 update_or_create() 方法中的默认参数。
假设您找到了一个基于过滤器的对象,现在应该选择和更新默认参数值。
如果没有根据过滤器找到匹配的对象,那么它将继续并创建一个带有过滤器的条目并传递默认参数。