3

我正在使用“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. 我不需要在我的“更新方案”中将此行添加到数据库
4

2 回答 2

2

最后我通过覆盖得到了它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
于 2017-02-09T10:35:04.800 回答
0

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

然后你可以这样做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)
        ...

在您对预览错误发表评论后,请记住这不是该应用程序的官方功能,因此您必须遵循堆栈跟踪并解决弹出的问题。我上面的第一个想法看起来是最快和最简单的方法,但是您可以尝试使elsefor save 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)
于 2017-02-09T08:35:34.123 回答