'Import-Export with "multilevel" models
I am figuring how can I manage this situation with django-import-export using the same excel and differents models with differents djangoapps. I have the following models:
# employees/models.py
class Employee(models.Model):
name = models.CharField(max_length=100)
job = models.ForeignKey(Job, on_delete=models.SET_NULL, null=True, blank=True)
# jobs/models.py
class Job(models.Model):
value = models.CharField(max_length=100)
department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True, blank=True)
place = models.ForeignKey(Place, on_delete=models.SET_NULL, null=True, blank=True)
class Department(models.Model):
value = models.CharField(max_length=100)
business = models.ForeignKey(Business, on_delete=models.SET_NULL, null=True, blank=True)
class Place(models.Model):
value = models.CharField(max_length=100)
business = models.ForeignKey(Business, on_delete=models.SET_NULL, null=True, blank=True)
class Business(models.Model):
name = models.CharField(max_length=100)
On excel I have following values:
xls_employee_name, xls_employee_job, xls_business_name
Jon Doe, Web Developer, Company 1
I know how to import employee name and his job because Job is directly related by ForeignKey. But how can I import business name?
Below is the code for employee name and his job:
# employees/resource.py
class EmpleadoResource(resources.ModelResource):
name = fields.Field(attribute='nombre', column_name='Nombre')
job = fields.Field(
column_name='xls_employee_job',
attribute='job',
widget=ForeignKeyWidget(
Job,
field='value'
))
class Meta:
model = Employee
fields = ('name','job',)
skip_unchanged = True
def before_import_row(self, row, **kwargs):
self.job = row["xls_employee_job"]
def after_import_instance(self, instance, new, row_number=None, **kwargs):
Job.objects.get_or_create(name=self.job)
Is it possible to import business name using one excel? I appreciate if someone could guide me. I'm also pretty new with django.
Solution 1:[1]
thank you for all your answers. I finally manage it and this is the solution(it was a little trickier for me, but very simple. I tried to translate all spanish names to english, sorry if I misslooked some):
# employees/resource.py
class EmployeeResource(resources.ModelResource):
name = fields.Field(attribute='name', column_name='Name')
job = fields.Field(
column_name='xls_employee_job',
attribute='job',
widget=ForeignKeyWidget(
Job,
field='value'
))
place = fields.Field(attribute='place', column_name='xls_place_column')
department = fields.Field(attribute='department', column_name='xls_department_column')
business = fields.Field(attribute='business', column_name='xls_business_name')
class Meta:
model = Employee
fields = ('name','job','place','department','business')
skip_unchanged = True
def before_import_row(self, row, **kwargs):
self.job = row["xls_employee_job"]
self.place = row["xls_place_column"]
self.department = row["xls_department_column"]
self.business = row["xls_business_name"]
def after_import_instance(self, instance, new, row_number=None, **kwargs):
Job.objects.get_or_create(name=self.job)
Centro.objects.get_or_create(name=self.centro)
Departamento.objects.get_or_create(name=self.departamento)
Empresa.objects.get_or_create(nombre=self.empresa)
I was stucked using widgets for business, department and place, but it was not necessary
Solution 2:[2]
Option 1
You can assign the column value for each row to a temporary attribute on the model (it doesn't matter that this attribute is not in the Employee model):
def before_import_row(self, row, **kwargs):
self.job = row["xls_employee_job"]
# assign row value to a temporary attr
self.business = row["xls_business_name"]
def after_import_instance(self, instance, new, row_number=None, **kwargs):
Job.objects.get_or_create(name=self.job)
# create instance using temp attr value
Business.objects.get_or_create(name=self.business)
Option 2
You can create all Business instances by processing the dataset in a batch before processing the Employee resources:
def before_import(self, dataset, using_transactions, dry_run, **kwargs):
for row in dataset.dict:
business = row["xls_business_name"]
Business.objects.create(name=business)
Note that you could use bulk_create() here to make this process more efficient.
Add transaction protection as you see fit, and bear in mind that the Business and Job entities will be created even if your import fails.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
