Django Проверка внешнего ключа электронной почты

У меня есть этот профильный ресурс:

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',)

, который проверяет 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',)

Он больше не подтверждает электронную почту. Я пробовал добавить два виджета, ForeignKeyWidget и CharWidget для email на InvestmentResource, но это не сработало.

Как мне затем подтвердить электронную почту внутри InvestmentResource?

Что происходит, так это то, что вы импортируете инвестиционный ресурс, который может быть чем-то вроде:

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

Вы настроили InvestmentResource на использование электронной почты в качестве ключа поиска для Profile. Это означает, что django-import-export будет обрабатывать его не как адрес электронной почты, а как ключ поиска для Profile, поэтому в коде (ForeignKeyWidget) он будет делать что-то вроде:

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

Если все прошло успешно, ваш экземпляр Investment теперь будет иметь правильный профиль в качестве ссылки на внешний ключ.

При этом будет возникать исключение DoesNotExist, если связанное с ним Profile отсутствует. Поэтому можно утверждать, что адрес электронной почты, отправленный в 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
Вернуться на верх