从Django import_export导入到表中

31moq8wy  于 2022-11-26  发布在  Go
关注(0)|答案(1)|浏览(175)

我正在努力使用ForeignKey在Django中填充models。假设我们有**import_export**文档中的以下示例:

class Author(models.Model):
    id = models.BigAutoField(primary_key=True)
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Category(models.Model):
    id = models.BigAutoField(primary_key=True)
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Book(models.Model):
    name = models.CharField('Book name', max_length=100)
    author = models.ForeignKey(Author, blank=True, null=True, )
    ...
    price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    categories = models.ManyToManyField(Category, blank=True)

    def __str__(self):
        return self.name

我如何实现import_export模块,该模块可以通过名称(而不是ID)检查是否存在一个现有的作者,该模块不区分大小写,并且可以在作者不存在的情况下生成一个新的作者
例如,假设CSV文件如下所示:

name,author,...,price,categories
J.R.R. Tolkien,Lord of the Rings,...,40,["cat1","cat2"]

另外,如果存在DateTime字段,如何在ForeignKey表中生成该字段?

**注意:**我知道自然密钥的用法:

from import_export.fields import Field
from import_export.widgets import ForeignKeyWidget

class AuthorManager(models.Manager):

    def get_by_natural_key(self, name):
        return self.get(name=name)

class Author(models.Model):

    objects = AuthorManager()

    name = models.CharField(max_length=100)
    birthday = models.DateTimeField(auto_now_add=True)

    def natural_key(self):
        return (self.name,)

# Only the author field uses natural foreign keys.
class BookResource(resources.ModelResource):

    author = Field(
        column_name = "author",
        attribute = "author",
        widget = ForeignKeyWidget(Author, use_natural_foreign_keys=True)
    )

    class Meta:
        model = Book

但是我不知道如何检查CSV中的UPPERlower情况,以及如果不存在,如何生成新的Author

bzzcjhmw

bzzcjhmw1#

如果FK关系尚不存在,有几种方法可以在导入过程中创建FK关系。

选项1 -覆盖before_import_row()方法

class BookResource(resources.ModelResource):

    # note use of 'iexact' for case-insensitive lookup
    def before_import_row(self, row, **kwargs):
        author_name = row["author"]
        Author.objects.get_or_create(name__iexact=author_name, 
            defaults={"name": author_name})

    # other code omitted

选项2 -子类ForeignKeyWidget

只需将ForeignKeyWidget子类化并在clean()中实现检查:

class AuthorForeignKeyWidget(widgets.ForeignKeyWidget):

    def clean(self, value, row=None, **kwargs):
        author, created = Author.objects.get_or_create(name__iexact=value,
            defaults={"name": value})
        return author

class BookResource(resources.ModelResource):
    author = fields.Field(
        column_name='author',
        attribute='author',
        widget=AuthorForeignKeyWidget(Author))

    # other code omitted

无论哪种方式都行。我个人会使用选项2。
另外,如果有DateTime字段,如何在ForeignKey表中生成?
由于您正在调用Author.objects.get_or_create(),因此可以根据需要添加日期,例如:

author, created = Author.objects.get_or_create(name__iexact=value, 
    defaults={"name": value, "created": timezone.now()})

如果使用自然关键点,则可以根据需要调整代码。
Related answer about creating in bulk mode

相关问题