如果电子邮件存在,django-import-export 更新配置文件

django-import-export update profile if email exists

我的 Profile model 上有这个 unique field:

email = models.EmailField(max_length=200, unique=True)

我有这个 ProfileResource:

class ProfileResource(resources.ModelResource):

    # associated_issuer = fields.Field(attribute='add_associated_issuer', widget=ManyToManyWidget(Issuer, field='name'), column_name='Associated Issuer')
    email = fields.Field(attribute='email', 
        widget=CharWidget(), 
        column_name='email')

    class Meta:
        model = Profile
        clean_model_instances = True
        import_id_fields = ('id', 'email')

    def before_import_row(self, row, row_number=None, **kwargs):
        try:
            self.email = row["email"] 
        except Exception as e:
            self.email = ""

        try:
            if row["id"] == '':
                row["id"] = None
                self.id = row["id"] 
        except Exception as e:
            self.id = None

        try:
           self.firstname = row["firstname"] 
        except Exception as e:
            self.firstname = ""

        try:
           self.lastname = row["lastname"]
        except Exception as e:
            self.lastname = ""

现在,当我尝试从文件导入时,收到此错误:

我需要能够执行 update_or_create 方法,但是我应该在哪里添加该代码?我尝试在 after_import_instance 上执行此操作,但没有成功。

我也试过 import_row 这样的:

def import_row(self, row, instance_loader, using_transactions=True, dry_run=False, **kwargs):
    try:
        Profile.objects.update_or_create(email=self.email)
    except Exception as e:
        print(e, file=sys.stderr)

但它产生了这个错误:

Exception Value: 'NoneType' object has no attribute 'import_type'

任何关于修复的见解都将不胜感激。

#try this 

email = models.EmailField(max_length=200, unique=True, null=True)

        try:
            self.email = row["email"] 
        except Exception as e:
            self.email = None

unique=True 也阻止重复的 "",但不阻止 null。

请注意,您的 ProfileResource

上有此行

import_id_fields = ('id', 'email')

这意味着导入将查看导入文件中的每一行,并尝试加载匹配 idemail 的任何 Profile 个实例。

因此,如果您只需要更新 email,那么只需将其从 import_id_fields 的列表中删除即可。通过这样做,逻辑将仅基于 id 来唯一标识实例,然后如果新记录不存在则将创建新记录,并且将更新任何现有记录(包括更新电子邮件地址)。

这就是 import-export 的工作方式,不需要进一步的逻辑。

如果 email 是匹配您现有实例的“唯一字段”,那么这应该是 import_id_fields 中的唯一字段。不能有两个 Profile 实例具有相同的电子邮件,因为 unique=True,因此您可以使用 email 作为 import_id_field。但是,将无法使用 import-export 更新 Profile 电子邮件(尽管您可以引入一个名为 new_email 的字段并具有以这种方式更新 Profile 的逻辑,但是是一个单独的主题)。

我不知道您为什么会看到 'email already exists' 错误 - 可能是其他原因造成的,可能是 before_import_row() 中的逻辑导致了问题,可能是由于使用空字符串作为电子邮件创建行的事实。

顺便说一句 - 你不应该需要 before_import_row() 中的任何逻辑 - import-export 应该为你处理这个,并且通过覆盖你可能会引入更多的错误。

使用 import-export 的最佳建议是在 IDE 中设置断点,然后在导入过程中单步执行,您可以准确地看到发生了什么。这将在漫长的 运行.

中为您节省大量时间

总而言之,在 import_id_fields 中使用 idemail 应该可以。

你应该尝试改变

import_id_fields = ('id', 'email')

来自

import_id_fields = ('email',)

当您尝试导入 ID 为空的行时,它将始终被视为新行。所以在这种情况下它会创建而不是更新。但是当你在 import_id_fields 中只留下 email 时,它显然会进行更新而不是创建。

你试过了吗?