#django #django-import-export
Вопрос:
У меня есть эти две модели:
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
s ImportExportModelAdmin
для массового импорта и экспорта, но когда я пытаюсь импортировать, я получаю эту ошибку:
Я понимаю, что это приводит к этой ошибке, потому что профиль еще не создан. Но что мне нужно сделать, чтобы реализовать update_or_create
внутри ImportExportModelAdmin
?
Комментарии:
1. Я никогда не пользовался этим раньше, но, может быть, вы могли бы попробовать это. Создайте резервные модели и импортируйте данные, которые вы будете импортировать в эти модели, но в этих моделях при подключении профиля к
Investment
модели укажитеon_delete=models.SET_NULL
иnull=True, blank=True
свойства. Затем вы можете заполнить поле профиляInvestment
модели и перенести его в основные модели через оболочку.
Ответ №1:
Вариант 1-использовать before_import()
для сканирования набора данных и пакетного создания профилей, если они еще не существуют.
Вариант 2-переопределить методы и создать профили непосредственно перед Investment
импортом строки. Это необходимо только для новых Investment
объектов. Это предполагает , что «электронная почта» будет однозначно идентифицировать a Profile
, вам нужно будет скорректировать это, если нет.
Обратите внимание, что firstname
и lastname
может быть установлено для Profile
объекта до его создания.
class InvestmentResource(resources.ModelResource):
firstname = fields.Field(attribute='profile__firstname',
widget=CharWidget(), column_name='firstname')
lastname = fields.Field(attribute='profile__lastname',
widget=CharWidget(), column_name='lastname')
email = fields.Field(attribute='email',
widget=ForeignKeyWidget(Profile, field='email'),
column_name='email')
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 Profile.objects.filter(
name=self.email
).exists()
):
obj, created = Profile.objects.get_or_create(
name=self.email
)
if created:
logger.debug(f"no Profile in db with name='{self.email}' - created")
instance.profile = obj
Очевидно, что создание профиля будет побочным эффектом импорта, поэтому вам может потребоваться рассмотреть возможность использования транзакций, если вы не хотите, чтобы профили создавались в случае сбоя импорта.
Комментарии:
1. Привет, похоже, он сможет создать экземпляр после просмотра журналов с указанным выше кодом . Но он по-прежнему показывает, что запрос на сопоставление профиля ошибки не существует.
2. возможно, он вызывается на этапе «предварительного просмотра» (т. Е. Если вы используете интерфейс администратора). Лучше всего установить отладчик и пройти через него, чтобы вы могли видеть, что происходит.
3. Хорошо. Я так и сделаю, спасибо!
4. привет, не могли бы вы удалить комментарий со ссылкой на чат, пожалуйста? Я не смог заблокировать все поля в одном изображении. Спасибо!
5. хорошо, это было сделано