Django:在.get()检索的单个模型实例上调用.update()?

时间:2012-09-12 05:33:47

标签: python django models

我有一个当前调用Models.object.get()的函数,它返回0或1个模型对象。如果它返回0,我在函数的except DoesNotExist子句中创建一个新的模型实例。否则,我想更新预先存在的实例中的字段,而不创建新的字段。我最初试图在找到的实例上调用.update(),但.update()似乎只能在QuerySets上调用。如何在不调用.filter()的情况下更改十几个字段并比较长度以了解我是否必须创建或更新预先存在的实例?

7 个答案:

答案 0 :(得分:48)

随着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

答案 1 :(得分:34)

从Django 1.5开始,模型保存上有一个update_fields属性。例如:

obj.save(update_fields=['field1', 'field2', ...])

https://docs.djangoproject.com/en/dev/ref/models/instances/

我更喜欢这种方法,因为如果您有多个Web应用程序实例更改模型实例的不同部分,它不会产生原子性问题。

答案 2 :(得分:21)

如果您只想更新模型(如果存在)(不创建它):

uint32_t *disp_addr = &temp;
...
error_lower = *(uint8_t *)(disp_addr+0);

mysql查询:

Model.objects.filter(id = 223).update(field1 = 2)

答案 3 :(得分:19)

我不知道这有多好或多坏,但你可以尝试这样的事情:

try:
    obj = Model.objects.get(id=some_id)
except Model.DoesNotExist:
    obj = Model.objects.create()
obj.__dict__.update(your_fields_dict) 
obj.save()

答案 4 :(得分:6)

这是一个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方法适用于您希望更新模型的时间,并且您知道实例已保存到数据库中,直接回答原始问题。内置{{1 Platinum Azure中的方法回答已经涵盖了其他用例。)

您可以像这样使用它(在将其混合到您的用户模型中之后):

update_or_create

除了拥有更好的API之外,这种方法的另一个优点是它调用user = request.user user.update(favorite_food="ramen") pre_save挂钩,同时如果另一个进程正在更新同一模型,仍然可以避免原子性问题。

答案 5 :(得分:0)

在这种情况下我使用以下代码:

obj, created = Model.objects.get_or_create(id=some_id)

if not created:
   resp= "It was created"
else:
   resp= "OK"
   obj.save()

答案 6 :(得分:0)

如@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