Django 验证电子邮件外键

标签 django django-import-export

我有这个配置文件资源:

class ProfileResource(resources.ModelResource):
    email = fields.Field(attribute='email', 
        widget=CharWidget(), 
        column_name='email')

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

在创建配置文件时验证电子邮件。它工作正常,但是当我将它用作外键时,例如:

class InvestmentResource(resources.ModelResource):
    email = fields.Field(attribute='email', 
        widget=ForeignKeyWidget(Profile, field='email'), 
        column_name='email')

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

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

    def after_import_instance(self, instance, new, row_number=None, **kwargs):
        """
        Create any missing Profile entries prior to importing rows.
        """
        try:
            profile, created = Profile.objects.get_or_create(email=self.email)

            profile.firstname = self.profile__firstname
            profile.lastname = self.profile__lastname
            profile.save()

            instance.profile = profile

        except Exception as e:
            print(e, file=sys.stderr)

它不再验证电子邮件。我尝试为 InvestmentResource 上的电子邮件添加两个小部件,ForeignKeyWidgetCharWidget,但没有成功。

然后如何验证 InvestmentResource 中的电子邮件?

最佳答案

问题是您的“电子邮件”字段被视为查找键而不是电子邮件地址。这可以通过自定义 ForeignKeyWidget 来添加电子邮件验证来解决。

发生的事情是您正在导入投资资源,它可能类似于:

email,firstname,lastname
bob@example.com,bob,smith

您已将 InvestmentResource 配置为使用电子邮件作为 Profile 的查找键。这意味着 django-import-export 不会将其作为电子邮件地址处理,而是作为 Profile 的查找键进行处理,因此在代码中 (ForeignKeyWidget ) 它将做类似的事情:

Profile.objects.get(email='bob@example.com')

如果成功,您的 Investment 实例现在将具有正确的配置文件作为外键引用。

如果关联的 Profile 不存在,这将引发 DoesNotExist 异常。因此,您可以争辩说,在 csv 中发送的电子邮件地址必须有效,因为如果无效,则无法进行查找。

但是,如果您想在尝试加载 Profile 之前检查电子邮件在语法上是否有效,那么这很容易做到,您需要覆盖 ForeignKeyWidget首先执行验证:

from django.core.exceptions import ValidationError
from django.core.validators import validate_email

class ValidatingForeignKeyWidget(widgets.ForeignKeyWidget):

    def clean(self, value, row=None, *args, **kwargs):
        
        try:
            validate_email(value)
        except ValidationError as e:
            # a quirk of import-export means that the ValidationError 
            # should be re-raised
            raise ValueError(f"invalid email {e}")
    
        try:
            val = super().clean(value)
        except self.model.DoesNotExist:
            raise ValueError(f"{self.model.__name__} with value={value} does not exist")
        return val

关于Django 验证电子邮件外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69761522/

相关文章:

django - 如何减去两个日期并获得注释中的天数?

python - 在 Django 中有没有办法将选项显示为复选框?

python - 在此服务器上找不到所请求的 URL。 Django

Django-import-export 更改/删除上传文件中不存在的针对数据库的记录

python - 使用 django-import-export 导出并显示相关对象的详细名称

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

javascript - django 提供的index.html 无法找到socket.io 服务器

mysql - Django ORM : group records by a field and then get the records with max field value in each group

python - 如何修复 Django 中的错误 "invalid literal for int() with base 10: ' Independence'?

python - 如何在admin外使用Django-import-export ImportForm和ConfirmImportForm