我有一个函数,当前调用Models.object.get()
,它返回0或1个模型对象。如果它返回0,我在函数的except DoesNotExist
子句中创建一个新的模型实例。否则,我想更新预先存在的实例中的字段,而不创建新的字段。我原本试图在找到的实例上调用.update()
,但.update()
似乎只能在QuerySets上调用。如何在不调用.filter()
的情况下更改十几个字段并比较长度以了解我是否必须创建或更新预先存在的实例?
随着Django 1.7的出现,现在有一个新的update_or_create
QuerySet方法,它应该完全符合你的要求。如果在数据库级别没有强制执行唯一性,请注意潜在的竞争条件。
文档中的示例:
obj, created = Person.objects.update_or_create(
first_name='John', last_name='Lennon',
defaults={'first_name': 'Bob'},
)
update_or_create
方法尝试根据给定的kwargs从数据库中获取对象。如果找到匹配项,则会更新defaults
字典中传递的字段。
Pre-Django 1.7:
根据需要更改模型字段值,然后调用.save()
以保留更改:
try:
obj = Model.objects.get(field=value)
obj.field = new_value
obj.save()
except Model.DoesNotExist:
obj = Model.objects.create(field=new_value)
# do something else with obj if need be
从Django 1.5开始,模型保存中有一个update_fields属性。例如:
obj.save(update_fields=['field1', 'field2', ...])
https://docs.djangoproject.com/en/dev/ref/models/instances/
我更喜欢这种方法,因为如果您有多个Web应用程序实例更改模型实例的不同部分,它不会创建原子性问题。
如果你只想更新模型,如果存在(不创建它):
Model.objects.filter(id = 223).update(field1 = 2)
mysql查询:
UPDATE `model` SET `field1` = 2 WHERE `model`.`id` = 223
我不知道这有多好或多坏,但你可以尝试这样的事情:
try:
obj = Model.objects.get(id=some_id)
except Model.DoesNotExist:
obj = Model.objects.create()
obj.__dict__.update(your_fields_dict)
obj.save()
这是一个mixin,你可以混合到任何模型类中,为每个实例提供一个update
方法:
class UpdateMixin(object):
def update(self, **kwargs):
if self._state.adding:
raise self.DoesNotExist
for field, value in kwargs.items():
setattr(self, field, value)
self.save(update_fields=kwargs.keys())
self._state.adding
检查检查模型是否保存到数据库,如果没有,则引发错误。
(注意:这个update
方法适用于您想要更新模型的时候,并且您知道实例已经保存到数据库中,直接回答了原始问题.Platin Azure中的内置update_or_create
方法的答案已涵盖其他用途 - 案件。)
您可以像这样使用它(在将其混合到您的用户模型中之后):
user = request.user
user.update(favorite_food="ramen")
除了拥有更好的API之外,这种方法的另一个优点是它调用pre_save
和post_save
钩子,同时如果另一个进程正在更新同一模型,仍然可以避免原子性问题。
在这种情况下我使用以下代码:
obj, created = Model.objects.get_or_create(id=some_id)
if not created:
resp= "It was created"
else:
resp= "OK"
obj.save()
正如@Nils所提到的,您可以使用update_fields
方法的save()
关键字参数手动指定要更新的字段。
obj_instance = Model.objects.get(field=value)
obj_instance.field = new_value
obj_instance.field2 = new_value2
obj_instance.save(update_fields=['field', 'field2'])
update_fields
值应该是要更新为字符串的字段列表。
见https://docs.djangoproject.com/en/2.1/ref/models/instances/#specifying-which-fields-to-save