Let's suppose we have Author and Book models:
class Author(models.Model):
first_name = models.CharField(max_length=60)
last_name = models.CharField(max_length=60)
def __str__(self):
return self.last_name
class Book(models.Model):
title = models.CharField(max_length=60)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
def __str__(self):
return self.title
And we try to do multiple inserts using CSV files:
(author.csv)
FirstNameA, LastNameA
FirstNameB, LastNameB
(book.csv)
FirstTitle, LastNameA
AnotherTitle, LastNameA
OneMoreTitle, LastNameB
I try to build a class-based view which imports a CSV in a model.
The view:
- is given the name of the model as an argument
- fetches the model and its fields and uses
get_or_createmethod in a loop for each row of the CSV.
.
class ImportCSV(View):
...
def post(self, request, model_name):
model = apps.get_model('app', model_name)
fields = list(modelform_factory(model=model, fields='__all__').base_fields.keys())
file = request.FILES['csv_file']
decoded_file = file.read().decode('utf-8').splitlines()
reader = csv.reader(decoded_file)
for row in reader:
dict = {}
for i, field in enumerate(fields):
dict[field] = row[i]
_, created = model.objects.get_or_create(**dict)
While it works for Author model, it does not work for Book model, due to ForeignKey field. It expects an id (number), not the value that __str__ returns for this record. It is totally logical. The question is, how can I handle such an import? What I would like to tell Django to do is:
If it is a foreign key, find the id of the book that is associated with this string (last name).
PS: I know that ID and Last Name may not be a 1-to-1 relationship, I just leave it as is for this example