Django: создать объект из CSV с внешним ключом

У меня есть 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      |

как устроен ваш CSV-файл? Что у вас есть в строке ['категория']?

Ozgur Akcali 09.04.2019 22:16
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
1 460
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как говорит ошибка, вы должны сначала получить соответствующий объект из БД, чтобы иметь возможность его назначить:

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 »должен быть экземпляром« Категории ».

Ozgur Akcali 09.04.2019 22:46

Другие вопросы по теме