如果 Django ImportExportModelAdmin 中不存在则创建对象
Create object if not exists in 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
进行批量导入和导出,但是当我尝试导入时,出现此错误:
我知道它会产生此错误,因为尚未创建配置文件。但是我需要做什么才能在 ImportExportModelAdmin
中实现 update_or_create
?
选项 1 是使用 before_import()
扫描数据集并批量创建配置文件(如果尚不存在)。
选项 2 是覆盖方法并在导入 Investment
行之前创建配置文件。这仅对新的 Investment
对象是必需的。这里假设 'email' 将唯一标识一个 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
显然,配置文件创建将是导入的副作用,因此如果您不想在导入失败时创建配置文件,则可能需要考虑使用事务。
我有这两个型号:
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
进行批量导入和导出,但是当我尝试导入时,出现此错误:
我知道它会产生此错误,因为尚未创建配置文件。但是我需要做什么才能在 ImportExportModelAdmin
中实现 update_or_create
?
选项 1 是使用 before_import()
扫描数据集并批量创建配置文件(如果尚不存在)。
选项 2 是覆盖方法并在导入 Investment
行之前创建配置文件。这仅对新的 Investment
对象是必需的。这里假设 'email' 将唯一标识一个 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
显然,配置文件创建将是导入的副作用,因此如果您不想在导入失败时创建配置文件,则可能需要考虑使用事务。