Combining PostgreSQL Enum with TypeDecorator

Is there a way to create an Enum class that will be created automatically when creating a new database, for example, the standard Enum, but also connect it to the TypeDecorator , which starts process_bind_param ?

This first block of code creates an Enum type that automatically reduces data entry before saving, but, unlike a regular Enum , a specific PostgreSQL enumeration type is automatically created in the database, so run create_all() throws an error when creating the table, because language_code does not exist in the PostgreSQL schema.

 class LowercaseEnum(sqlalchemy.types.TypeDecorator): '''Converts input to lowercase.''' impl = sqlalchemy.types.Enum def process_bind_param(self, value, dialect): return value.lower() class Foo(Model): id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) language_code = sqlalchemy.Column(LowercaseEnum(*['de', 'en'], name='language_code')) 

If, on the other hand, I define my custom type, as in this second block of code, then it is automatically created when create_all() called, but the process_bind_param method is never called when sending values ​​to the database, so the lower case does not work.

 class LowercaseEnum(sqlalchemy.dialects.postgresql.ENUM, sqlalchemy.types.TypeDecorator): '''Converts input to lowercase.''' impl = sqlalchemy.types.Enum def process_bind_param(self, value, dialect): return value.lower() 

I also tried several different inheritance combinations from TypeDecorator in a separate class that was mixed, and also switched to sqlalchemy.types.Enum and sqlalchemy.dialects.postgresql.ENUM , but it seems that no matter what I do, I either get a class that is created automatically, or a class that starts process_bind_param , but never both.

+4
source share
1 answer

This seems to work, although it would be great if anyone knows a better solution or sees a problem with it.

 class LowercaseEnum(sqlalchemy.types.TypeDecorator, sqlalchemy.types.SchemaType): '''Converts input to lowercase.''' impl = sqlalchemy.dialects.postgresql.ENUM def _set_table(self, table, column): self.impl._set_table(table, column) def process_bind_param(self, value, dialect): return value.lower() 
+2
source

Source: https://habr.com/ru/post/1484483/


All Articles