Створіть модель Джанго або оновіть її, якщо вона існує


115

Я хочу створити об'єкт моделі, наприклад 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

Але я не знаю, де перевірити та отримати наявний об’єкт людини.

Відповіді:


169

Якщо ви шукаєте "використання оновлення, якщо існує ще створити", будь ласка, зверніться до @Zags відмінної відповіді


Джанго вже є get_or_create, https://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

Я використовую django 1.9, і він дає мені: AttributeError: 'QuerySet' об’єкт не має атрибута 'update_or_create'
Ofek Gila

1
@OfekGila Це дивно, як вихідний код і документація підтвердження QuerySetмаєupdate_or_create
Bakkal

2
У моєму випадку, замість ідентифікатора, у мене є група полів, яка утворює унікальний_збіг. Яке використання в цьому випадку?
Ракмо

191

Незрозуміло, чи задає ваше запитання метод 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}
)

12
+1 для, update_or_createтому що для цього випадку використання краще, ніж get_or_createпросто зателефонувати save()на об’єкт ще раз.
bakkal

У моєму випадку, замість ідентифікатора, у мене є група полів, яка утворює унікальний_збіг. Яке використання в цьому випадку?
Ракмо

1
@OmkarDeshpande ідентифікатор - лише приклад; Ви можете передати будь-який дійсний запит про Person.objects.get_or_create(a=a, b=b, c=c, defaults={"name": name})
джанго

Що робити, якщо я хочу додати до створеної Особи більше полів, ніж поля за замовчуванням?
Ло

@LoBellin defaultsаргументом цих функцій є те, де ви вказуєте, які поля ви хочете додати до моделі. Це не має нічого спільного з типовими значеннями, вказаними на полях вашої моделі
Zags

10

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

4

Для лише невеликої кількості об'єктів 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 () може бути варіантом.


3

Думаю, я б додав відповідь, оскільки назва вашого запитання виглядає так, що він запитує, як створити або оновити, а не отримати або створити так, як описано в тілі запитань.

Якщо ви хочете створити або оновити об’єкт, метод .save () вже має цю поведінку за замовчуванням у документах :

Django резюмує необхідність використання операторів INSERT або UPDATE SQL. Зокрема, під час виклику save (), Django дотримується цього алгоритму:

Якщо для атрибута первинного ключа об'єкта встановлено значення, що оцінює значення True (тобто значення, відмінне від None, або порожній рядок), Django виконує UPDATE. Якщо атрибут первинного ключа об'єкта не встановлений або якщо UPDATE нічого не оновив, Django виконує ВСТУП.

Варто зазначити, що коли вони говорять "якщо UPDATE нічого не оновлював", вони по суті посилаються на випадок, коли ідентифікатор, який ви дали об'єкту, вже не існує в базі даних.


1

Якщо один із вхідних даних при створенні є первинним ключем, цього буде достатньо:

Person.objects.get_or_create(id=1)

Він автоматично оновлюється, якщо існує, оскільки два дані з тим самим первинним ключем не дозволені.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.