Django import-export - Import model with child from excel

I have two models: Project and Activity.
When registering a project, one or more associated activities can be added.

How can I import projects from xlsx, which include at least one activity?. I'm using the third party library django-import-export

I configure the project resource to export all the activities of each project in one cell separated by /, but I need the opposite, import all the activities of each project. I think that I must first save the Project for obtain the id, next extract the info from cell and finally save each activity associated, but I don't know how to do that.

My simplified models are:

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

An example of exported file is:

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

You need to create the Activity instances before you create the Project instances.

Then in your Project resource class you can define that a particular field is for foreign keys.

I've got an example;

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

When using the ForeignKeyWidget, the first argument is the related model, then the second is a unique value that you can use to lookup the instance. It's that unique value that you then put in your import file to reference the related objects.

And my Token model has that relationship;

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,
    )
Back to Top