Создать, если не существует

81

У меня есть приложение Django, которое считывает данные из веб-API и помещает их в базу данных.
Есть ли способ создать новый объект из режима, но предотвратить дублирование исключения, если объект уже существует?

Другими словами, есть ли способ сохранить объект, но ничего не делать, если он уже существует?

user1094786
источник

Ответы:

161

Model.objects.get_or_create()

второй
источник
9
создание ссылки на документы добавляет некоторые символы (и, я думаю, это лучший ответ)
второй
4
Кажется, это 2 запроса. Если я хочу сохранить объект только на случай, если он не существует, есть ли способ с одним запросом? Я предполагаю, что перехват IntegrityErrorприведет к прерыванию текущей транзакции, и этого недостаточно.
Амир Али Акбари
вы можете поймать ошибку целостности при добавлении точки сохранения, например , с помощью transaction.atomic(убедитесь , что вы ловите снаружи в atomicблок, то есть try: with acomic: create; except IntegrityErrorэто также сложно убедиться , что вы не ловите. другие ошибки целостности , чем тот , который вы намерены
второй
Если вы можете уловить IntegrityError, мое тестирование показывает, что оно сокращает время выполнения почти вдвое, когда существует запись, по сравнению с get_or_create().
Рон
3

Похоже, что в новых версиях Django функция save () по умолчанию выполняет UPDATE или INSERT. Смотрите здесь .

Crperez
источник
похоже, что он должен выбирать автоматически, однако в моем db он в настоящее время дублирует записи каждый раз, когда я запускаю свой скрипт для заполнения db.
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 (), за исключением необязательного аргумента, называемого defaults, будут использоваться для запроса в базе данных (поиска объекта) в базе данных.

Он возвращает кортеж, если объект найден, 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()
Абхишек Пратап Сингх
источник