首页 > 解决方案 > 如果在 Django ImportExportModelAdmin 中不存在,则创建对象

问题描述

我有这两个模型:

Profile_model.py

class Profile(models.Model):
    firstname = models.CharField(max_length=200, blank=False)
    lastname = models.CharField(max_length=200, blank=False)
    email = models.CharField(max_length=200, unique=True, blank=False)
    ...

投资模型.py

class Investment(models.Model):
    invested = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True)
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    ...

我有这个管理员:

投资管理.py

class InvestmentResource(resources.ModelResource):
    ...
    firstname = fields.Field(attribute='profile', 
        widget=ForeignKeyWidget(Profile, field='firstname'), 
        column_name='firstname')
    lastname = fields.Field(attribute='profile', 
        widget=ForeignKeyWidget(Profile, field='lastname'), 
        column_name='lastname')
    email = fields.Field(attribute='email', 
        widget=ForeignKeyWidget(Profile, field='email'), 
        column_name='email')
    class Meta:
        model = Investment
        fields = (
            'firstname',
            'lastname',
            'email',
            'invested',)
        
        export_order = fields


class InvestmentAdmin(ImportExportModelAdmin, admin.ModelAdmin):
        ...
        resource_class = InvestmentResource
        ...

我正在使用django'sImportExportModelAdmin进行批量导入和导出,但是当我尝试导入时,出现此错误:

在此处输入图像描述

我知道它会产生此错误,因为尚未创建配置文件。但是我必须做些什么来实现update_or_create内部ImportExportModelAdmin

标签: djangodjango-import-export

解决方案


选项 1before_import()用于扫描数据集并批量创建配置文件(如果它们尚不存在)。

Investment选项 2 是在导入行之前覆盖方法并创建配置文件。这仅对新Investment对象是必需的。这假设 'email' 将唯一标识 a Profile,如果不是,您将需要调整它。

请注意,firstname可以lastnameProfile对象创建之前对其进行设置。

class InvestmentResource(resources.ModelResource):
    firstname = fields.Field(attribute='profile__firstname', 
        widget=CharWidget(), column_name='firstname')

    lastname = fields.Field(attribute='profile__lastname', 
        widget=CharWidget(), column_name='lastname')

    email = fields.Field(attribute='email', 
        widget=ForeignKeyWidget(Profile, field='email'), 
        column_name='email')

    def before_import_row(self, row, row_number=None, **kwargs):
        self.email = row["email"]

    def after_import_instance(self, instance, new, row_number=None, **kwargs):
        """
        Create any missing Profile entries prior to importing rows.
        """
        if (
            new
            and not Profile.objects.filter(
                name=self.email
            ).exists()
        ):
            obj, created = Profile.objects.get_or_create(
                name=self.email
            )
            if created:
                logger.debug(f"no Profile in db with name='{self.email}' - created")
                instance.profile = obj

显然,配置文件创建将是导入的副作用,因此如果您不希望在导入失败时创建配置文件,则可能需要考虑使用事务。


推荐阅读