152

我想创建一个模型对象,比如 Person,如果人的 id 不存在,或者我会得到那个人对象。

创建新人的代码如下:

class Person(models.Model):
    identifier = models.CharField(max_length = 10)
    name = models.CharField(max_length = 20)
    objects = PersonManager()

class PersonManager(models.Manager):
    def create_person(self, identifier):
        person = self.create(identifier = identifier)
        return person

但我不知道在哪里检查和获取现有的 person 对象。

4

8 回答 8

247

目前尚不清楚您的问题是要求get_or_create方法(至少可从 Django 1.3 获得)还是update_or_create方法(Django 1.7 中的新方法)。这取决于您要如何更新用户对象。

样品使用如下:

# In both cases, the call will get a person object with matching
# identifier or create one if none exists; if a person is created,
# it will be created with name equal to the value in `name`.

# In this case, if the Person already exists, its existing name is preserved
person, created = Person.objects.get_or_create(
        identifier=identifier, defaults={"name": name}
)

# In this case, if the Person already exists, its name is updated
person, created = Person.objects.update_or_create(
        identifier=identifier, defaults={"name": name}
)
于 2014-10-09T19:52:49.040 回答
196

如果您正在寻找“如果存在则更新”用例,请参阅@Zags 出色的答案


Django 已经有一个get_or_createhttps://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create

对你来说可能是:

id = 'some identifier'
person, created = Person.objects.get_or_create(identifier=id)

if created:
   # means you have created a new person
else:
   # person just refers to the existing one
于 2013-01-01T23:46:07.120 回答
11

Django 对此有支持,请检查get_or_create

person, created = Person.objects.get_or_create(name='abc')
if created:
    # A new person object created
else:
    # person object already exists
于 2013-01-01T23:48:01.757 回答
6

update_or_create仅适用于少量对象,但如果您正在处理大型集合,则它不会很好地扩展。update_or_create总是先运行 SELECT,然后运行 ​​UPDATE。

for the_bar in bars:
    updated_rows = SomeModel.objects.filter(bar=the_bar).update(foo=100)
        if not updated_rows:
            # if not exists, create new
            SomeModel.objects.create(bar=the_bar, foo=100)

这充其量只会运行第一个更新查询,并且只有当它匹配零行时才会运行另一个 INSERT 查询。如果您希望大多数行实际存在,这将大大提高您的性能。

不过,这一切都取决于您的用例。如果您期望主要是插入,那么也许bulk_create()命令可能是一个选项。

于 2018-11-15T13:25:28.160 回答
4

我想我会添加一个答案,因为您的问题标题看起来像是在询问如何创建或更新,而不是按照问题正文中的描述获取或创建。

如果您确实想要创建或更新对象,则 .save() 方法默认情况下已经具有此行为,来自文档

Django 抽象了使用 INSERT 或 UPDATE SQL 语句的需要。具体来说,当你调用 save() 时,Django 遵循这个算法:

如果对象的主键属性设置为计算结果为 True 的值(即,非 None 或空字符串的值),Django 执行 UPDATE。如果对象的主键属性没有设置或者 UPDATE 没有更新任何东西,Django 执行一个 INSERT。

值得注意的是,当他们说“如果 UPDATE 没有更新任何内容”时,他们实质上是指您提供给对象的 id 不存在于数据库中的情况。

于 2014-06-24T08:57:49.147 回答
4

您也可以像 get_or_create 一样使用 update_or_create ,这是我为 update_or_create 遵循的模式,假设模型 Person 具有 id(键)、name、age、is_manager 作为属性 -

update_values = {"is_manager": False}
new_values = {"name": "Bob", "age": 25, "is_manager":True}

obj, created = Person.objects.update_or_create(identifier='id',
                                               defaults=update_values)
if created:
    obj.update(**new_values)
于 2020-12-17T23:49:34.020 回答
1

如果您创建时的输入之一是主键,这就足够了:

Person.objects.get_or_create(id=1)

如果存在,它将自动更新,因为不允许具有相同主键的两个数据。

于 2016-08-03T11:01:04.353 回答
0

这应该是您正在寻找的答案

EmployeeInfo.objects.update_or_create(
    #id or any primary key:value to search for
    identifier=your_id, 
    #if found update with the following or save/create if not found
    defaults={'name':'your_name'}
)
于 2020-11-03T00:22:00.030 回答