Створити, якщо не існує


81

У мене є програма Django, яка зчитує дані з веб-API та розміщує їх у базі даних.
Чи є спосіб створити новий об’єкт із режиму, але запобігти повторення винятку, якщо об’єкт уже існує?

Іншими словами, чи є спосіб зберегти об’єкт, але просто не робити нічого, якщо він уже існує?

Відповіді:


161

9
посилання на документи додає символів (і, мабуть, робить це кращою відповіддю)
друге

4
Здається, це робить 2 запити. Якщо я хочу зберегти об’єкт лише у випадку, якщо він не існує, чи є спосіб із лише 1 запитом? Я вважаю, що зловживання IntegrityErrorспричиняє переривання поточної транзакції та є недостатнім.
Амір Алі Акбарі

ви можете зловити помилку цілісності при додаванні точки збереження, наприклад , з допомогою transaction.atomic(переконайтеся , що ви ловите зовні в atomicблок, тобто try: with acomic: create; except IntegrityErrorце також складно переконатися , що ви не ловите. інші помилки цілісності , ніж той , який ви маєте намір
другий

Якщо ви зможете зловити IntegrityError, моє тестування показує, що це скорочує час виконання майже вдвічі, коли запис існує порівняно з get_or_create().
Рон,


3

Схоже, у нових версіях Django функція save () за замовчуванням виконує ОНОВЛЕННЯ або ВСТАВЛЕННЯ. Дивіться тут .


схоже, він повинен вибирати добре автоматично, однак у моїй базі даних він наразі дублює записи кожного разу, коли я запускаю свій сценарій для заповнення бази даних.
martin-martin

метод save () перевіряє, чи має значення PK моделі. Автору довелося б запитати БД, щоб отримати екземпляр моделі з правильним PK, щоб використовувати цю техніку. Виключне використання функції save () не робить магії.
chickahoona

0

Цього можна досягти за допомогою Model.objects.get_or_create()

Приклад

obj, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

Будь-які ключові аргументи (тут first_name і last_name ) передається в get_or_create () - за винятком опціонального називаються дефолти - будуть використовуватися для запиту в базі даних (знайти об'єкт) в базі даних.

Він повертає кортеж, якщо об'єкт знайдено, get_or_create () повертає кортеж цього об'єкта та False.

Примітка : Те саме можна також досягти за допомогою try exceptтверджень
Приклад:

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.