创建Django模型或更新(如果存在)

问题:创建Django模型或更新(如果存在)

我想创建一个模型对象,例如Person,如果不存在person的id,或者我将得到该person对象。

创建新人员的代码如下:

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

但是我不知道在哪里检查并获取现有的人对象。

I want to create a model object, like Person, if person’s id doesn’t not exist, or I will get that person object.

The code to create a new person as following:

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

But I don’t know where to check and get the existing person object.


回答 0

如果您正在寻找“如果存在则更新,否则会创建”用例,请参阅@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

If you’re looking for “update if exists else create” use case, please refer to @Zags excellent answer


Django already has a get_or_create, https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create

For you it could be :

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

回答 1

目前尚不清楚您的问题是否要求使用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}
)

It’s unclear whether your question is asking for the get_or_create method (available from at least Django 1.3) or the update_or_create method (new in Django 1.7). It depends on how you want to update the user object.

Sample use is as follows:

# 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}
)

回答 2

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

Django has support for this, check get_or_create

person, created = Person.objects.get_or_create(name='abc')
if created:
    # A new person object created
else:
    # person object already exists

回答 3

对于仅少量的对象,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()命令。

For only a small amount of objects the update_or_create works well, but if you’re doing over a large collection it won’t scale well. update_or_create always first runs a SELECT and thereafter an 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)

This will at best only run the first update-query, and only if it matched zero rows run another INSERT-query. Which will greatly increase your performance if you expect most of the rows to actually be existing.

It all comes down to your use case though. If you are expecting mostly inserts then perhaps the bulk_create() command could be an option.


回答 4

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

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

Django提取了使用INSERT或UPDATE SQL语句的需求。具体来说,当您调用save()时,Django遵循以下算法:

如果对象的主键属性设置为计算结果为True的值(即,无或空字符串以外的值),则Django将执行UPDATE。如果未设置对象的主键属性,或者UPDATE未更新任何内容,则Django执行INSERT。

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

Thought I’d add an answer since your question title looks like it is asking how to create or update, rather than get or create as described in the question body.

If you did want to create or update an object, the .save() method already has this behaviour by default, from the docs:

Django abstracts the need to use INSERT or UPDATE SQL statements. Specifically, when you call save(), Django follows this algorithm:

If the object’s primary key attribute is set to a value that evaluates to True (i.e., a value other than None or the empty string), Django executes an UPDATE. If the object’s primary key attribute is not set or if the UPDATE didn’t update anything, Django executes an INSERT.

It’s worth noting that when they say ‘if the UPDATE didn’t update anything’ they are essentially referring to the case where the id you gave the object doesn’t already exist in the database.


回答 5

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

Person.objects.get_or_create(id=1)

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

If one of the input when you create is a primary key, this will be enough:

Person.objects.get_or_create(id=1)

It will automatically update if exist since two data with the same primary key is not allowed.