Как я могу игнорировать вставку дубликата в Django?

У меня есть несколько статических таблиц, которые я инициализирую с помощью команды управления.

Suit(name = "Clubs").save()
Suit(name = "Hearts").save()
Suit(name = "Diamonds").save()
Suit(name = "Spades").save()

Я хочу иметь возможность повторно запустить это в любое время, если появятся новые значения, но я хочу избежать вставки дубликатов. База данных имеет уникальное ограничение, поэтому при наличии дубликатов я получаю сообщение об ошибке. Помимо упаковки каждого отдельного оператора в try/catch, есть ли способ запустить несколько таких операторов, игнорировать нарушение ограничений и продолжать работу?

Поскольку код идентичен, за исключением фактических значений, составьте список значений и напишите один цикл с одним try..except…?

deceze 11.07.2024 14:19
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
51
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вместо того, чтобы звонить .save(), я бы позвонил .get_or_create(), как описано здесь.

Suit.objects.get_or_create(name = "Clubs")
Suit.objects.get_or_create(name = "Hearts")
Suit.objects.get_or_create(name = "Diamonds")
Suit.objects.get_or_create(name = "Spades")

у нас обоих один и тот же ответ 😅

Sharim09 11.07.2024 14:28

Спасибо. это именно то, что я искал. Извините, что не могу принять оба ответа :-)

Peter Kronenberg 11.07.2024 14:35
Ответ принят как подходящий

Либо вы можете использовать метод @deceze, который уже упоминался, то есть использовать список и try-except.

или вы можете использовать метод get_or_create

Удобный метод поиска объекта по заданным кваргам (может быть пустым, если в вашей модели есть значения по умолчанию для всех полей), создание объекта при необходимости.

for ele in lst: # the list of data
    Suit.objects.get_or_create(ele)

Если количество объектов (здесь четыре) невелико, мы можем работать с .get_or_create(…) [Django-doc]. Однако это не будет хорошо масштабироваться, если мы загрузим ~100 или более элементов в базу данных, поскольку это приведет как минимум к ~100 запросам.

В этом случае мы можем работать с двумя запросами: сначала посмотреть, какие элементы уже есть в базе данных, а затем вставить недостающие в один запрос, например:

items = [
    ('Clubs',),
    ('Hearts',),
    ('Diamonds',),
    ('Spades',),
]

field_names = ('name',)
model = Suit

existing = set(model._base_manager.values_list(*field_names))

model._base_manager.bulk_create(
    [
        model(**dict(zip(field_names, item)))
        for item in items
        if item not in existing
    ]
)

Его также можно использовать с другими полями, например:

model = Card
item = [
    ('Spades', 4),
]
field_names = ('kind', 'value')

Другие вопросы по теме