Reputation:
Suppose I have such models:
class Recipe (models.Model):
par_recipe = models.CharField(max_length=200)
class Line (models.Model):
par_machine = models.CharField(max_length=200)
class Measurements (models.Model):
par_value = models.IntegerField(default=0)
id_line = models.ForeignKey(Line)
id_recipe = models.ForeignKey(Recipe)
Do I understand correctly that in this way I have a 1: 1 relationship, and adding entries ids will be automatically created id_line,id_recipe
.
I will add for example:
for row in ws.iter_rows(row_offset=1):
recipe =Recipe()
line = line()
measurements = Measurements()
recipe.par_recipe = row[1].value
line.par_machine = row[2].value
measurements.par_value = row[8].value
And the small question about measurements was conceived that all secondary keys should go to it, now it is implemented correctly?
Upvotes: 2
Views: 46
Reputation: 1991
It is not quite like that, you would have to tie them together:
for row in ws.iter_rows(row_offset=1):
recipe =Recipe.objects.create(par_recipe=row[1].value)
line = Line.objects.create(par_machine=row[2].value)
measurements = Measurements.objects.create(
par_value=row[8].value,
id_line=line,
id_recipe=recipe
)
None of this is db optimized, you could use transactions to optimize the db writes.
You could make it faster if there are a lot of rows by using transactions:
from django.db import transaction
with transaction.atomic():
for row in ws.iter_rows(row_offset=1):
recipe =Recipe.objects.create(par_recipe=row[1].value)
line = Line.objects.create(par_machine=row[2].value)
measurements = Measurements.objects.create(
par_value=row[8].value,
id_line=line,
id_recipe=recipe
)
This would create a transaction and write one instead of each time. But it will also fail the whole transaction on an error.
see Django Database Transactions
You could get more creative by counting the number of records and writing every 1000 records for example by:
from django.db import transaction
with transaction.atomic():
for idx, row in enumerate(ws.iter_rows(row_offset=1)):
recipe =Recipe.objects.create(par_recipe=row[1].value)
line = Line.objects.create(par_machine=row[2].value)
measurements = Measurements.objects.create(
par_value=row[8].value,
id_line=line,
id_recipe=recipe
)
# every 1000 records, commmit the transaction
if idx % 1000 == 0:
transaction.commit()
Upvotes: 2
Reputation: 476557
Do I understand correctly that in this way I have a 1: 1 relationship, and adding entries ids will be automatically created id_line,id_recipe.
The relations will not link to the previously constructed objects, that would also be quite unsafe since a small change to the code fragment, could result in a totally different way of linking elements together.
Furthermore a ForeignKey
is a many-to-one relation: multiple Measurements
objects can refer to the same Recipe
object.
You need to do this manually, for example:
for row in ws.iter_rows(row_offset=1):
recipe = Recipe.objects.create(par_recipe=row[1].value)
line = Line.objects.create(par_machine=row[2].value)
measurements = Measurements.objects.create(
par_value=row[8].value,
id_line=line,
id_recipe=recipe
)
Note that a ForeignKey
refers to the objects, not to the primary key value, so you probably want to rename your ForeignKey
s. A model typically has a singular name, so Measurement
instead of Measurements
:
class Measurement(models.Model):
par_value = models.IntegerField(default=0)
line = models.ForeignKey(Line, on_delete=models.CASCADE)
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
Upvotes: 1