Reputation: 29
I am writing a rest api service in python that talks to a Postgres database. I am using flake-sqlalchemy to do so. In the table, one of the columns is defined as:
my_column my_type not null
And my_type is defined:
create type my_type as emum ('val1', 'val2', 'val3')
How do I represent this in flask-sqlalchemy? Thanks you for you help.
Upvotes: 0
Views: 596
Reputation: 2126
your app.py definition goes like this:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from sqlalchemy.types import TypeDecorator, CHAR
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://test:test@localhost/test?charset=utf8mb4'
db = SQLAlchemy(app)
Migrate(app, db, compare_type=True)
class CustEnum(TypeDecorator):
impl = CHAR(4)
def process_bind_param(self, value, dialect):
valid_values = ('val1', 'val2', 'val3')
if value not in valid_values:
raise TypeError(f"mismatch {value} not in {valid_values} ")
return value
class Blobby(db.Model):
id = db.Column(db.Integer, primary_key=True)
type_col = db.Column(CustEnum())
where the process_bind_param
method is basically the setter method and process_result_value
is the getter method.
refer to doc for more on it https://docs.sqlalchemy.org/en/14/core/custom_types.html#sqlalchemy.types.TypeDecorator
I also like to add a test function to the file with the cli decorator to check it works.
@app.cli.command("testit")
def testit():
newblob = Blobby(type_col = 'val2')
db.session.add( newblob )
db.session.commit()
for row in db.session.execute('select * from blobby'):
print(row)
input('press enter to continue to failure test')
# value not allowed should fail
newblob = Blobby(type_col = 'fail')
db.session.add( newblob )
db.session.commit()
When you apply the migration (i.e running flask db init
, flask db migrate
and flask db upgrade
), you get an error that name app.CustEnum cant be found.
sa.Column('type_col', app.CustEnum(length=4), nullable=True),
NameError: name 'app' is not defined
Searching for a fix for that I found the author of the library says you need to update the migration script itself which is kinda backwards IMO.
https://github.com/miguelgrinberg/Flask-Migrate/issues/282#issuecomment-518989508
so just edit migrations/versions/98f29efa609f_.py
or whatever your version is. and add import app
or whatever your flask script's namespace is.
last thing is to run the test with flask testit
to run the testit() function to give you one success and one failure.
sqlalchemy.exc.StatementError: (builtins.TypeError) mismatch fail not in ('val1', 'val2', 'val3')
[SQL: INSERT INTO blobby (type_col) VALUES (%(type_col)s)]
[parameters: [{'type_col': 'fail'}]]
Upvotes: 1