Django import-export - Импорт модели с дочерними элементами из excel
У меня есть две модели: Project
и Activity
.
При регистрации проекта можно добавить одну или несколько связанных с ним работ.
Как я могу импортировать проекты из xlsx, которые включают хотя бы одну деятельность? Я использую стороннюю библиотеку django-import-export
Я настраиваю ресурс проекта на экспорт всех видов деятельности каждого проекта в одну ячейку, разделенную /
, но мне нужно наоборот, импортировать все виды деятельности каждого проекта. Я думаю, что сначала я должен сохранить Project
для получения id
, затем извлечь информацию из ячейки и, наконец, сохранить каждую связанную с ней деятельность, но я не знаю, как это сделать.
Мои упрощенные модели таковы:
class Project(models.Model):
reg_date= models.DateField(
default=date.today)
name = models.CharField(
max_length=100,
unique=True)
def __str__(self):
return self.name
class Activity(models.Model):
schedule= models.ForeignKey(
Project,
on_delete=models.CASCADE)
date = models.DateField()
description = models.TextField(max_length=1000)
class Meta:
unique_together = ('schedule', 'date', 'description')
class ProjectResource(resources.ModelResource):
activities = Field()
class Meta:
model = Project
import_id_fields = ['name']
exclude = ('id',)
skip_unchanged = True
report_skipped = True
fields = ('reg_date',
'name',
'activities')
def dehydrate_activities(self, obj):
if obj.id:
return "/".join([
'({0} - {1})'.format(activity.date, activity.description) for activity in obj.projectactivity_set.all()
])
def skip_row(self, instance, original, row, import_validation_errors=None):
if original.name:
return True
return False
Примером экспортированного файла является:
reg_date | name | activities |
---|---|---|
2023-01-10 | Project 1 | 2023-01-12-This is the first activity/2023-01-14-This is the second activity |
2023-01-10 | Project 2 | 2023-01-13-This is the first activity/2023-01-15-This is the second activity |
Вам необходимо создать Activity
экземпляры до создания Project
экземпляров.
Затем в своем классе ресурсов Project
вы можете определить, что определенное поле предназначено для внешних ключей.
У меня есть пример;
from import_export import fields, resources, widgets
from apps.event.models import Occurrence
from ..models import Token
class TokenResource(resources.ModelResource):
""" Integrate django-import-export with the Token model """
occurrence = fields.Field(
column_name='occurrence',
attribute='occurrence',
widget=widgets.ForeignKeyWidget(Occurrence, 'id')
)
class Meta:
fields = (
'id',
'occurrence',
'code',
)
model = Token
При использовании ForeignKeyWidget
первым аргументом является связанная модель, а вторым - уникальное значение, которое можно использовать для поиска экземпляра. Именно это уникальное значение вы затем помещаете в файл импорта для ссылки на связанные объекты.
И моя модель Token
имеет эту связь;
class Token(EnabledMixin, TimestampMixin, models.Model):
""" Token for event entry. """
class Meta:
""" Meta class definition. """
app_label = 'console'
verbose_name = _("Token")
verbose_name_plural = _("Tokens")
unique_together = ('code', 'occurrence')
ordering = [
'id',
]
occurrence = models.ForeignKey(
to='event.Occurrence',
verbose_name=_("Event Occurrence"),
blank=True,
null=True,
related_name='tokens',
on_delete=models.SET_NULL,
)