我有2种型号:Category
和Product
,并且我都需要从CSV文件中上传两者。
为Category
模型上传CSV数据时,我可以这样做,因为它没有ForeignKey字段。
但是尝试从Product
模型从CSV上载数据时出现错误。因为它具有Category模型的ForeignKey。
ValueError:无法分配“'Stickers'”:“ Product.category”必须为 “类别”实例。
有可能吗?我可以将该字段保留为空白,以后不要求手动进行此操作,但是理想的情况是自动执行此操作。
commands / 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)
models.py:
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:
categories.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. | | |
products.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 |
答案 0 :(得分:3)
就像错误提示一样,您必须先从数据库中获取相应的对象才能进行分配:
category = Category.objects.get(id=row['category'])
但是有一个快捷方式:
category_id = row['category']
注意_id
,可让您直接分配外键(=所引用对象的主键)。
使用此功能时,在将对象写入数据库之前,您显然不会注意到无效的外键。
如果您的CSV文件中确实有类别名称而不是ID,那么您肯定首先需要找到相应的数据库对象:
category = Category.objects.get(category=row['category'])
您可以将其包装在try / except中,以准备缺少的类别;幸运的是,类别名称上有一个唯一的约束,因此,多个具有相同名称的对象将不会成为问题。