pythonormpeewee

Appending additional '_id' to a field


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.

desired ERD

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.

Update

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.


Solution

  • 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.