I have the following model:
class Sample(MAFwBaseModel):
sample_id = AutoField(primary_key=True, help_text='The sample id primary key')
sample_name = TextField(help_text='The sample name')
class Resolution(MAFwBaseModel):
resolution_id = AutoField(primary_key=True, help_text='The resolution id primary key')
resolution_value = FloatField(help_text='The resolution in µm')
class CalibrationMethod(MAFwBaseModel):
method_id = AutoField(primary_key=True, help_text='The primary key for the calculation method')
multiplier = FloatField(default=1., help_text='The multiplication factor of this method')
class Image(MAFwBaseModel):
image_id = AutoField(primary_key=True, help_text='The image id primary key')
sample_id = ForeignKeyField(Sample, on_delete='CASCADE', backref='+')
filename = TextField()
checksum = TextField()
resolution_id = ForeignKeyField(Resolution,on_delete='CASCADE', backref='+')
class ProcessedImage(MAFwBaseModel):
image_id = ForeignKeyField(Image, primary_key=True, backref='+', help_text='The image id, foreign key and primary', on_delete='CASCADE')
value = FloatField(default=0)
With this definition, I could build exactly the DB in the way I wished.
The relationships between the Image and the other three tables is perfect as shown in the ERD below.
Now, I want to make a cross join with with CalibrationMethod and to do so, I use the following query.
cross_join = (ProcessedImage.select(ProcessedImage, CalibrationMethod)
.join(CalibrationMethod, JOIN.CROSS)
.execute()
)
The query, in itself, works ok, meaning that I get exactly what I wanted, but when I start looping over the rows, I have found something strange:
for row in cross_join:
# the image_id of ProcessedImage is not what I was expecting:
row.image_id # is the row in Image
row.image_id_id # is the field in ProcessedImage
row.method_id # is the field in CalibrationMethod.
I don't understand why sometimes a second '_id' it is added to the attribute. It is only a problem with the attribute, because the columns in the database are all correctly named.
This makes me thinking it is not a bug, but rather a feature and that I am overlooking something. What am I missing? There must be a page of the documentation that I have skipped.
I have read the page on lazy_load
in the documentation. If I specify lazy_load = False, then both the row.image_id and row.image_id_id will be the actual field value.
Moreover, if I leave lazy_load = True and I specify object_id_name = 'ref_image_id', then row.image_id will point to Image row and row.ref_image_id to the value of the field. I would have rather preferred the opposite, the possibility to change the name of the row and not the one the field.
We follow Django standard where:
Foreign key is named the "noun" of the object you are relating to. The simplest example would be:
sample = ForeignKeyField(Sample, on_delete='CASCADE', backref='+')
Then in your code you can use:
image.sample # Resolve the related object.
Or:
image.sample_id # Just the corresponding sample's ID value.