【问题标题】:Django import export: update without addDjango导入导出:更新而不添加
【发布时间】:2017-02-08 19:28:58
【问题描述】:

我正在使用 'django import export' (DIE) 来导入和更新一些数据。

导入过程从检查数据库中存在的对象开始,按 ID 字段中的值搜索,如果没有找到来自导入文件的 ID 行 - 将创建新条目。我如何制作“仅更新”场景,如果在 DB 中找不到“id key”,则将跳过行(不添加新的)?

我的模型.py

class Size(models.Model):
    id = models.AutoField(unique=True, primary_key=True, null=False, blank=False)
    height = models.SmallIntegerField()
    width = models.SmallIntegerField()


class Product(models.Model):
    id = models.AutoField(unique=True, primary_key=True, null=False, blank=False)
    vendor_code = models.CharField(unique=True, max_length=50, null=False, blank=False)
    price = models.DecimalField(null=False, blank=False)
    size = models.ForeignKey(Size, verbose_name=u'Size')

在资源.py中

class ProductSyncResource(resources.ModelResource):

    class Meta:
        model = ProductVariant
        import_id_fields = ('vendor_code',)
        fields = ('vendor_code', 'price',)
        export_order = ('vendor_code', 'price', 'status', )
        skip_unchanged = True
        report_skipped = True
        dry_run = True

导入表 (xls)

如果没有找到 vendor_code 'Tк-12856'(单元格 A3),则 DIE 将尝试添加此行,并且:

  1. 我们会从数据库中得到错误(外键检查列“大小”)
  2. 我不需要在“更新方案”中将此行添加到数据库中

【问题讨论】:

    标签: django django-import-export


    【解决方案1】:

    最后我通过覆盖skip_row 得到了它。字段现在可以是“null=False”,并且只会导入具有已知 import_id_field 值的行。

    class VariantSyncResource(resources.ModelResource):
    
        class Meta:
            model = ProductVariant
            import_id_field = 'vendor_code'
            import_id_fields = ('vendor_code',)
            fields = ('vendor_code', 'price', 'status', )
            export_order = ('vendor_code', 'price', 'status', )
            skip_unchanged = True
            report_skipped = False
            dry_run = True
    
        def skip_row(self, instance, original):
            original_id_value = getattr(original, self._meta.import_id_field)
            instance_id_value = getattr(instance, self._meta.import_id_field)
            if original_id_value != instance_id_value:
                return True
            if not self._meta.skip_unchanged:
                return False
            for field in self.get_fields():
                try:
                    if list(field.get_value(instance).all()) != list(field.get_value(original).all()):
                        return False
                except AttributeError:
                    if field.get_value(instance) != field.get_value(original):
                        return False
            return True
    

    【讨论】:

    • 这是一个不错的解决方案!
    【解决方案2】:

    如果您希望它不创建新对象,我认为您需要覆盖 ProductSyncResource 中的 import_row()

    那你就可以if new: return;

    def import_row(self, row, instance_loader, using_transactions=True, dry_run=False, **kwargs):
    
        row_result = self.get_row_result_class()()
        try:
            self.before_import_row(row, **kwargs)
            instance, new = self.get_or_init_instance(instance_loader, row)
            self.after_import_instance(instance, new, **kwargs)
            if new:
                return row_result
            else:
                row_result.import_type = RowResult.IMPORT_TYPE_UPDATE
            row_result.new_record = new
            original = deepcopy(instance)
            ...
    

    在您对预览错误发表评论后,请记住这不是应用程序的官方功能,因此您只需关注堆栈跟踪并解决弹出的问题。我上面的第一个想法看起来是最快和最简单的方法,但您可以尝试将 else 用于保存 save 以新对象为条件;

                elif not new:
                    with transaction.atomic():
                        self.save_instance(instance, using_transactions, dry_run)
                    self.save_m2m(instance, row, using_transactions, dry_run)
                diff.compare_with(self, instance, dry_run)
    

    【讨论】:

    • 我认为其他地方有问题..在预览屏幕上我得到了第一个错误:'(1048,“列'size_id'不能为空”)'。如果我更改数据库中的列设置以允许 Null,那么在导入屏幕中我仍然有“将被添加”的行
    • @NikitaBel 好的,这不是一项功能,因此您必须继续使用覆盖来查看是否可以解决此问题。看看它保存实例的这一行。如果它是一个新实例,您可能会检查不保存; github.com/django-import-export/django-import-export/blob/…
    猜你喜欢
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 1970-01-01
    • 2017-01-07
    相关资源
    最近更新 更多