Как массово создавать или обновлять в Django

#python-3.x #django

Вопрос:

Я должен обрабатывать CSV-файл отчета об элементах каждые 1 час. CSV содержит более 150 000 записей для 1 учетной записи, и в моей системе есть несколько учетных записей. Я ранее работал на rails, и там был активный рекордный камень, который очень эффективно справлялся с этим случаем использования. Я ищу альтернативу этому драгоценному камню в Django или любому встроенному методу, который будет полезен для массового импорта таких больших данных.

До сих пор я пробовал этот код.

 class ItemReportService:

    def call(self, file_url):
        with open(file_url, 'r') as file:
            reader = csv.DictReader(file)
            products = []
            for row in reader:
                product = self.process_product(row)
                products.append(product)

            self.update_products(products)

    def process_product(self, row):
        print(f'Processing sku: {row["SKU"]}')
        product = Product.objects.filter(
            sku=row['SKU']).first() or Product(sku=row['SKU'])
        product.listing_title = row['Product Name']
        product.listed_price = row['Price']
        product.buy_box_price = row['Buy Box Item Price']   
            row['Buy Box Shipping Price']
        product.status = row['Lifecycle Status']
        return product

    def update_products(self, products):
        Product.objects.bulk_update(
            products,
            [
                'listing_title',
                'listed_price',
                'buy_box_price',
                'Lifecycle Status'
            ]
        )
 

Это вызывает это исключение, потому что при появлении нового продукта ему не присвоен первичный ключ

Ошибка значения: Все объекты bulk_update() должны иметь набор первичных ключей.

Комментарии:

1. Вы должны сначала создать и получить/отфильтровать объекты. Затем передайте массовое обновление экземпляров объектов.

2. Спасибо, Шива, я уже пробовал это. Я хочу найти продукт только на основе артикула, чтобы он вызывал ошибку, не оставляющую остальные поля пустыми.

3. Спасибо, что Джеймс получил его.

Ответ №1:

Вы не сохраняете продукт в базе данных перед применением bulk_update. Я проверил ваш код для этой цели, вы можете использовать bulk_insert с дополнительным параметром

 Model.objects.bulk_create(self.data, ignore_conflicts=True)
 

или

 columns = ['column1', 'column2']
obj = Model.objects.filter(column1="sku").first()
if not obj:
   obj = Model.objects.create(column1="sku")
obj.column1 = row["column1"] or obj.column1
obj.column2 = row["column2"] or obj.column2
items_to_be_inserted.append(obj)
 

В конце концов, вы можете выполнить массовое обновление, например

 Model.objects.bulk_update(items_to_be_inserted, columns)
 

Это решит вашу проблему.

Комментарии:

1. Обратите внимание, что это не работает для PostgreSQL

2. Если объекты уже существуют в базе данных, это будет игнорировать их

3. Обновил ответ.