Создайте объект, если он не существует в Django ImportExportModelAdmin

У меня есть эти две модели:

Profile_model.py

class Profile(models.Model):
    firstname = models.CharField(max_length=200, blank=False)
    lastname = models.CharField(max_length=200, blank=False)
    email = models.CharField(max_length=200, unique=True, blank=False)
    ...

Investment_model.py

class Investment(models.Model):
    invested = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True)
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    ...

и у меня есть этот администратор:

Investment_admin.py

class InvestmentResource(resources.ModelResource):
    ...
    firstname = fields.Field(attribute='profile', 
        widget=ForeignKeyWidget(Profile, field='firstname'), 
        column_name='firstname')
    lastname = fields.Field(attribute='profile', 
        widget=ForeignKeyWidget(Profile, field='lastname'), 
        column_name='lastname')
    email = fields.Field(attribute='email', 
        widget=ForeignKeyWidget(Profile, field='email'), 
        column_name='email')
    class Meta:
        model = Investment
        fields = (
            'firstname',
            'lastname',
            'email',
            'invested',)
        
        export_order = fields


class InvestmentAdmin(ImportExportModelAdmin, admin.ModelAdmin):
        ...
        resource_class = InvestmentResource
        ...

Я использую django'ImportExportModelAdmin для массового импорта и экспорта, но когда я пытаюсь импортировать, я получаю эту ошибку:

enter image description here

Я понимаю, что он выдает эту ошибку, потому что профиль еще не создан. Но что мне нужно сделать, чтобы реализовать update_or_create внутри ImportExportModelAdmin?

Вариант 1 - использовать before_import() для сканирования набора данных и пакетного создания профилей, если они еще не существуют.

Вариант 2 - переопределить методы и создать профили непосредственно перед импортом строки Investment. Это необходимо только для новых объектов Investment. Здесь предполагается, что 'email' будет однозначно идентифицировать профиль, если это не так, вам нужно будет скорректировать это.

class InvestmentResource(resources.ModelResource):

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

    def after_import_instance(self, instance, new, row_number=None, **kwargs):
        """
        Create any missing Profile entries prior to importing rows.
        """
        if (
            new
            and not models.Profile.objects.filter(
                email=self.email
            ).exists()
        ):
            _, created = models.Profile.objects.get_or_create(
                email=email
            )
            if created:
                logger.debug(f"no Profile in db with email='{self.email}' - created")

Очевидно, что создание профиля будет побочным эффектом импорта, поэтому вам может понадобиться рассмотреть возможность использования транзакций, если вы не хотите, чтобы профили создавались в случае неудачи импорта.

Вернуться на верх