Я работаю над веб-сайтом, на котором я хочу заполнить данные о продукте из внешнего API. Этот api содержит данные о сотнях продуктов, и у каждого продукта есть десятки вариантов. Каждый продукт и данные имеют свои изображения, которые я использую ImageField Django из моделей для локального хранения. Теперь проблема в том, что существует более 15000 изображений, а заполнение данных изображений занимает целую вечность. Вот структура API:
{
...
Single Product Image: ...
{ Product Variant1: ..., [list of 4 images] }
{ Product Variant2: ..., [list of 4 images] }
{ Product Variant3: ..., [list of 4 images] }
}
Каждый продукт имеет где-то от 10-50 вариаций. Вот что я сделал. Для изображений вариантов я использую таблицу отношений «многие-к-одному» для хранения всех изображений каждого варианта:
models.py:
class ProductsVariation(models.Model):
....
class VariationImages(models.Model):
prd_id = models.ForeignKey(ProductsVariation, on_delete=models.CASCADE)
img = models.ImageField(
upload_to=settings.MEDIA_ROOT + 'product_variation')
get_products.py:
from django.core.files import File
from tempfile import NamedTemporaryFile
import requests
for product in api_data: #Loop over main product
...
main_product_request = requests.get(product['IMAGE_NAME'])
main_img_temp = NamedTemporaryFile(delete=True)
main_img_temp.write(main_product_request.content)
main_img_temp.flush()
main_product.prd_img.save(product['GENERIC_NAME'] + ".jpg", File(main_img_temp), save=True)
main_product.save()
# Populate this product's variants
for variants in product['Product']: # Loop through each variant of this product
....
for img in variants['Images']: # For each variant, save their images to DB
vari = VariationImages.objects.create(prd_id=prd_variant)
vari_product_request = requests.get(img)
vari_img_temp = NamedTemporaryFile(delete=True)
vari_img_temp.write(vari_product_request.content)
vari_img_temp.flush()
vari.img.save(product['GENERIC_NAME'] + ".jpg", File(vari_img_temp), save=True)
vari.save()
Чтобы уточнить, изображение main_product и изображения вариантов go находятся в отдельных таблицах в БД. Другого способа сохранить изображения я не нашел. Может есть способ лучше хранить изображения из API? А может проблема в том, как я это делаю? Я не знаю, как это оптимизировать.
РЕДАКТИРОВАТЬ: После дополнительных испытаний я совершенно уверен, что узкое место возникает из-за файлов, сохраняемых на диск. Я попытался сохранить файлы прямо в локальное хранилище из URL-адресов API, и это оказалось очень медленным. Чтобы сохранить около 500 изображений, требуется примерно 30-40 секунд. Я пробовал использовать urllib.request.urlretrieve, Pillow и dload, BytesIO, но все они дают примерно одинаковый результат.