【问题标题】:Create object if not exists in Django ImportExportModelAdmin如果在 Django ImportExportModelAdmin 中不存在,则创建对象
【发布时间】:2021-10-03 20:55:49
【问题描述】:

我有这两个模型:

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)
    ...

Investment_model.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)
    ...

我有这个管理员:

Investment_admin.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
        ...

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

我知道它产生此错误是因为尚未创建配置文件。但是我需要做什么才能在ImportExportModelAdmin 中实现update_or_create

【问题讨论】:

  • 我以前从未使用过这个,但也许你可以试试这个。创建备份模型并将要导入的数据导入这些模型,但在这些模型中,将配置文件连接到Investment 模型时,请提供on_delete=models.SET_NULLnull=True, blank=True 属性。然后就可以填写Investment模型的profile字段,通过Shell传递给主模型。

标签: django django-import-export


【解决方案1】:

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

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

注意firstnamelastname可以在Profile对象创建之前设置。

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

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

【讨论】:

  • 您好,在查看logs 和您上面指定的code 后,似乎可以创建实例。但它仍然显示相同的错误配置文件匹配查询不存在。
  • 可能在“预览”阶段被调用(即,如果您使用的是管理界面)。最好设置一个调试器并单步执行,这样您就可以看到发生了什么。
  • 好的。我会的,谢谢!
  • 嗨,你能删除带有聊天链接的评论吗?我无法阻止一张图片中的所有字段。谢谢!
  • 好的,这已经完成了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 2022-11-19
  • 2016-12-20
  • 2021-02-28
  • 1970-01-01
相关资源
最近更新 更多