Sqlite3.IntegrityError: UNIQUE constraint failed | When using bulk adding many-to-many relation

У меня есть две модели, где одна из них имеет поле TreeManyToMany (поле "многие ко многим" для django-mptt моделей).

class ProductCategory(models.Model):
   pass

class Product(models.Model):
   categories = TreeManyToManyField('ProductCategory')

Я пытаюсь добавить категории к объектам Product массово с помощью сквозной таблицы, как показано в этой теме или в этой.

Я делаю это с помощью списка пар: product_id и productcategory_id, который также содержит моя сквозная таблица. Это приводит к следующей ошибке:

sqlite3.IntegrityError: UNIQUE constraint failed: products_product_categories.product_id, products_product_categories.productcategory_id

Мой код выглядит следующим образом:

def bulk_add_cats(generic_df):

    # A pandas dataframe where ["product_object"] is the product_id 
    # and ["found_categories"] is the productcategory_id to add to that product.
    generic_df = generic_df.explode("found_categories")
    generic_df["product_object"] = generic_df.apply(
        lambda x: Product.objects.filter(
            merchant = x["forhandler"], product_id = x["produktid"]
            ).values('id')[0]['id'], axis=1
    )
    
    # The actual code
    # Here row.product_object is the product_id and row.found_categories is one
    # particular productcategory_id, so they make up a pair to add to the through-table.
    through_objs = [
        Product.categories.through(
            product_id = row.product_object,
            productcategory_id = row.found_categories
        ) for row in generic_df.itertuples()
    ]
    Product.categories.through.objects.bulk_create(through_objs, batch_size=1000)

Я также сделал следующее, чтобы проверить, нет ли дублирующих пар в наборе пар, которые я хочу добавить. Их не было:

print(generic_df[generic_df.duplicated(subset=['product_object','found_categories'], keep=False)])

Я подозреваю, что ошибка возникает потому, что некоторые из отношений product-to-productcategory уже существуют в таблице. Так что, возможно, мне следует сначала проверить, так ли это, для каждой пары, а затем выполнить bulk_create. Я просто хочу надеяться на сохранение эффективности и буду огорчен, если мне придется итерировать каждую пару для проверки. Есть ли способ bulk-update-or-create для такого типа проблем?

Или что вы думаете? Любая помощь будет высоко оценена :-)

Вы, вероятно, должны проверить, не является ли причиной возникновения этих ошибок дублирование данных. Если это так, то я думаю, что параметр ignore_conflicts в bulk_create может решить вашу проблему. Он будет сохранять каждую действительную запись и игнорировать те, которые имеют дублирующий конфликт.

Проверьте документ: https://docs.djangoproject.com/en/3.2/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create

Вернуться на верх