У меня есть 2 модели: Category
и Product
, и мне нужно загрузить обе из файлов CSV.
Я могу сделать это при загрузке данных CSV для модели Category
, так как в ней нет поля ForeignKey.
Но я получаю сообщение об ошибке при попытке загрузить данные из CSV для модели Product
. Поскольку у него есть внешний ключ к модели категории.
ValueError: Cannot assign "'Stickers'": "Product.category" must be a "Category" instance.
Является ли это возможным? Я мог бы оставить это поле пустым и не запрашивать его позже вручную, но было бы идеально сделать это автоматически.
команды /products.py:
import pandas as pd
import csv
from shop.models import Product
from django.core.management.base import BaseCommand
tmp_data_products=pd.read_csv('static/data/products.csv',sep=',', encoding = "utf-8").fillna(" ")
class Command(BaseCommand):
def handle(self, **options):
products = [
Product(
category=row['category'],
product=row['product'],
slug=row['slug'],
description=row['description'],
size=row['size'],
quantity =row['quantity'],
price=row['image'],
available=row['available']
)
for _, row in tmp_data_products.iterrows()
]
Product.objects.bulk_create(products)
модели.ру:
class Category(models.Model):
category = models.CharField(max_length=250, unique=True)
slug = models.SlugField(max_length=250, unique=True)
description = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to='category', blank=True, null=True)
video = EmbedVideoField(null=True, blank=True)
class Product(models.Model):
product = models.CharField(max_length=250, unique=True)
slug = models.SlugField(max_length=250, unique=True)
description = models.TextField(blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
size = models.CharField(max_length=20, choices=TAMANIOS)
quantity = models.CharField(max_length=20, choices=CANTIDADES)
price = models.DecimalField(max_digits=10, decimal_places=2)
image = models.ImageField(upload_to='product', blank=True, null=True)
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
ОБНОВЛЕНИЕ 1:
категории.csv
| category | slug | description | image | video |
|-----------|-----------|----------------------------------------------------------------------|-------|-------|
| Imantados | imantados | Los mejores imantados en vinyl, acabado mate. Resistentes al agua. | | |
| Stickers | stickers | Los mejores stickers en vinyl, acabado mate. Resistentes al agua. | | |
| Muestras | muestras | Los mejores stickers en vinyl, acabado mate. Resistentes al agua. | | |
продукты.csv
| category | product | slug | description | size | quantity | price | image | available |
|----------|------------------------|------------------------|-----------------------------------------------------------------------|-----------|----------|-------|-------|-----------|
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 5cm x 5cm | 50 | 50 | | True |
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 5cm x 5cm | 100 | 70 | | True |
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 5cm x 5cm | 200 | 90 | | True |
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 5cm x 5cm | 300 | 120 | | True |
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 5cm x 5cm | 500 | 140 | | True |
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 5cm x 5cm | 1000 | 200 | | True |
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 5cm x 5cm | 2000 | 300 | | True |
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 7cm x 7cm | 50 | 70 | | True |
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 7cm x 7cm | 100 | 90 | | True |
| Stickers | Stickers transparentes | stickers-transparentes | Stickers Transparentes en Vinyl de alta calidad. Resistentes al agua. | 7cm x 7cm | 200 | 130 | | True |
Как говорит ошибка, вы должны сначала получить соответствующий объект из БД, чтобы иметь возможность его назначить:
category = Category.objects.get(id=row['category'])
Однако есть ярлык:
category_id = row['category']
Обратите внимание на _id
, который позволяет вам напрямую назначать внешний ключ (= первичный ключ указанного объекта).
При использовании этого вы, очевидно, не заметите недопустимый внешний ключ, пока не запишете объект в базу данных.
Если у вас действительно есть имена категорий, а не идентификаторы в вашем CSV-файле, вам определенно нужно сначала найти соответствующий объект базы данных:
category = Category.objects.get(category=row['category'])
Вы можете обернуть это в try/except, чтобы подготовиться к отсутствующим категориям; к счастью, существует уникальное ограничение на имя категории, поэтому несколько объектов с одинаковым именем не будут проблемой.
Я думаю, что у него есть имена категорий в CSV-файле: «Невозможно назначить« Наклейки »:« Product.category »должен быть экземпляром« Категории ».
как устроен ваш CSV-файл? Что у вас есть в строке ['категория']?