pythonenumspeewee

How to make the int values of an Enum to match the corresponding database record id?


I have a database table that contains specific companies that are accessed "statically" throughout the code and for which would be great to have a "static" way to refer to them, for example:

from enum import Enum, auto()

class CompanyEnum(Enum):
     APPLE = auto()
     AMAZON = auto()
     META = auto()
     

I would like the int value of the Enum to match the database id corresponding to those companies BUT of course I don't want the hardcoded id in the static Enum definition as that would be a terrible solution. Why would that be a terrible solution? because there is no guarantee that if the database is recreated from a backup or re-generated, the artificial ids will remain the same for those companies.

I can do something like (assuming that I am using Peewee):

from functools import lru_cache
from enum import Enum, auto()
from models import Company

class CompanyEnum(Enum):
     APPLE = auto()
     AMAZON = auto()
     META = auto()

     @lru_cache
     @property
     def id(self):
         company = Company.get(Company.name.upper() == self.name)
         return company.id
        

How can I make this dynamically resolved id property, the actual Enum int value?


Solution

  • The simplest solution is to get the names and ids with a function, and then use the functional API to to create the enum. Something like:

    CompanyEnum = Enum('CompanyEnum', get_names_ids('company'))
    

    and get_names_ids(column) is something like:

    def get_names_ids(column):
        # talk to dbs and get values of id and column fields
        return ... # [(id_1, company_1), (id_2, company_2), ...]
    

    The get_names_ids may have to ensure upper-case values, etc., but that's the basics.


    Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.