Как предотвратить действие сохранения в Django, чтобы избежать повторных вызовов БД для уже существующих данных

Мой текущий код для сохранения статей сохраняет новые статьи и печатает "The Post Already Exists!", если найден дубликат, но он все еще делает вызовы БД, и теперь у меня есть пробелы в ID в моей таблице статей из-за ложных сохранений, вызванных тем, что дубликаты статей не были сохранены. Как я могу улучшить свой код, чтобы предотвратить действие сохранения, если найден дубликат, чтобы сохранить последовательность идентификаторов статей?

if not Posts.objects.filter(title=post_title, slug=post_slug).exists():
   post = Posts(
        title = post_title,
        link = post_link,
        summary = post_summary,
        image_url = image_link,
        slug = post_slug,
        pub_date = date_published,
        guid = item.guid,
        feed_title = channel_feed_title,
        feed_link = channel_feed_link,
        feed_description = channel_feed_desc,
        source_id = selected_source_id,
        category_id = selected_category_id
       )
   post.save()

   for i in range(len(article_list)):
       post_tags = post.tags.add(article_list[i])

else:
   print("The Post Already Exists! Skipping...")

Я продолжаю получать такие ошибки:

django.db.utils.IntegrityError: duplicate key value violates unique constraint "Posts_posts_slug_key" DETAIL:  Key (slug)=() already exists.

Поскольку у вас есть только slug как уникальное поле, вы должны проверить, существует ли уже пост с таким же slug. Если нет, создайте его. Проблема, с которой вы столкнулись, заключается в том, что вы также проверяете заголовок (как оператор AND). Это может привести вас к мысли, что пост не существует, но вы все равно не можете добавить его в БД, потому что slug уже существует. Но не slug с другим названием. Это означает, что вам нужно удалить только заголовок в запросе:

Posts.objects.filter(slug=post_slug).exists()

Вот еще несколько методов решения проблемы, основанных на моем предыдущем ответе (https://docs.djangoproject.com/en/4.0/ref/models/querysets/#get-or-create):

try:
    post = Posts.objects.get(slug=post_slug)
except Posts.DoesNotExist:
    post = Posts(title=post_title, link=...)
    post.save()

В данном случае при одновременных запросах может быть предпринято несколько попыток сохранить пост с одинаковыми параметрами. Чтобы избежать этого состояния гонки, приведенный выше пример можно переписать с использованием get_or_create() следующим образом:

obj, created = Posts.objects.get_or_create(
    slug=post_slug,
    defaults={'title':post_title, 'link': ...},
)
Вернуться на верх