rar*_*iru 6 python django django-import-export
更新
我已提交功能请求。我们的想法是pass对IntegrittyError的时候由数据库产生unique或unique_together拒绝已经存在于数据库中的记录。
我有以下模型:
class Compositions(models.Model):
composer_key = models.ForeignKey(
Composer,
)
composition = models.CharField(
max_length=383,
)
class Meta(object):
unique_together = (('composer_key', 'composition'), )
Run Code Online (Sandbox Code Playgroud)
在管理界面中使用 django-import-export,而不为idcsv 文件中的每个条目提供一个,...如果一对 csv 文件已经存在,该过程将因完整性错误而中断
duplicate key value violates unique constraint "data_compositions_composer_key_id_12f91ce7dbac16bf_uniq"
DETAIL: Key (composer_key_id, composition)=(2, Star Wars) already exists.
Run Code Online (Sandbox Code Playgroud)
CSV 文件如下:
id composer_key composition
1 Hot Stuff
2 Star Wars
Run Code Online (Sandbox Code Playgroud)
这个想法是skip_row在管理员中使用和实现它。
管理.py:
class CompositionsResource(resources.ModelResource):
class Meta:
model = Compositions
skip_unchanged = True
report_skipped = True
class CompositionsAdmin(ImportExportModelAdmin):
resource_class = CompositionsResource
admin.site.register(Compositions, CompositionsAdmin)
Run Code Online (Sandbox Code Playgroud)
但是,这不会解决问题,因为skip_row需要idcsv 文件中的 ,以便检查每一行是否与非常特定的数据库条目相同。
考虑到这种控制可以由数据库在使用unique( _together)时进行,捕获此错误然后返回skip_row = True或pass在此错误上返回是否有效?
只需要一个 Change。你可以使用 django-import-export
模型.py
class Compositions(models.Model):
composer_key = models.ForeignKey(
Composer,
)
composition = models.CharField(
max_length=383,
unique=False
)
date_created = models.DateTimeField(default=timezone.now)
class Meta(object):
unique_together = (('composer_key','composition'),)
Run Code Online (Sandbox Code Playgroud)
用 try 覆盖 save_instance。并在失败时忽略错误。 管理文件
class CompositionsResource(resources.ModelResource):
class Meta:
model = Compositions
skip_unchanged = True
report_skipped = True
def save_instance(self, instance, using_transactions=True, dry_run=False):
try:
super(CompositionsResource, self).save_instance(instance, using_transactions, dry_run)
except IntegrityError:
pass
class CompositionsAdmin(ImportExportModelAdmin):
resource_class = CompositionsResource
admin.site.register(Compositions, CompositionsAdmin)
Run Code Online (Sandbox Code Playgroud)
并导入这个
from django.db import IntegrityError
Run Code Online (Sandbox Code Playgroud)
关于已接受答案的注释:它将给出所需的结果,但会严重影响大文件的磁盘使用率和时间。
我一直在使用的一种更有效的方法(在花费大量时间浏览文档之后)是重写skip_row,并使用一组元组作为类的一部分作为唯一约束。save_instance当然,我仍然按照其他答案的建议进行覆盖,以处理通过的 IntegrityErrors 。
Pythonsets不会创建重复的条目,因此它们似乎适合这种唯一索引。
class CompositionsResource(resources.ModelResource):
set_unique = set()
class Meta:
model = Composers
skip_unchanged = True
report_skipped = True
def before_import(self, dataset, using_transactions, dry_run, **kwargs):
# Clear out anything that may be there from a dry_run,
# such as the admin mixin preview
self.set_unique = set()
def skip_row(self, instance, original):
composer_key = instance.composer_key # Could also use composer_key_id
composition = instance.composition
tuple_unique = (composer_key, composition)
if tuple_unique in self.set_unique:
return true
else:
self.set_unique.add(tuple_unique)
return super(CompositionsResource, self).skip_row(instance, original)
# save_instance override should still go here to pass on IntegrityError
Run Code Online (Sandbox Code Playgroud)
这种方法至少会减少同一数据集中遇到的重复项。我用它来处理多个平面文件,每个文件大约有 60000 行,但有很多重复/嵌套的外键。这使得初始数据导入速度更快。