#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. Обновил ответ.