Search code examples
pythonpeewee

How to create dynamically generated value in PeeWee model?


In ORMs I've used so far, there was an option to add a value (field?) to model, that's not stored in database, but it's constructed using other values instead.

Here is quick example of how it could look like:

class MediaFile(BaseModel):
    ID = IntegerField()
    FileName = str(ID) + ".jpg"

So there is ID that's stored in database, and FileName that is constructed from ID. Above example of course doesn't work in PeeWee, because ID is IntegerField, not int I need.

How can I do such thing in PeeWee? How is it called?


Solution

  • Well, if you just want to access a property that is not stored in the database, remember that peewee models are just Python classes:

    class MediaFile(BaseModel):
        ID = AutoField()  # You should probably use this for auto-inc IDs.
    
        @property
        def FileName(self):
            return str(self.ID) + '.jpg'
    

    For more complex operations that you wish to be able to use both as SQL constructs and as computed instance values, see hybrid properties. An example of using hybrid properties:

    class Interval(Model):
        start = IntegerField()
        end = IntegerField()
    
        @hybrid_property
        def length(self):
            return self.end - self.start
    
        @hybrid_method
        def contains(self, point):
            return (self.start <= point) & (point < self.end)
    

    With this hybrid property and hybrid method, we can use the properties either in SQL queries or on model instances. So we end up being able to do things like:

    query = Interval.select().where(Interval.contains(2))
    

    Would generate the following SQL:

    SELECT "id", "start", "end"
    FROM "interval" AS t1
    WHERE (("start" <= 2) AND (2 < "end"))
    

    But we could also do:

    obj = Interval(start=1, end=10)
    obj.contains(2)  # returns True