Как предотвратить действие сохранения в 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': ...},
)