简体   繁体   中英

How to define `ENUM` field using flask_sqlalchemy?

Here is my code:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import enum

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root1234@localhost/kaka_db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True
db = SQLAlchemy(app)

class UserType(enum.Enum):
    puTongUser      = 0
    guanLiYuan      = 1
    superGuanLiYuan = 2
    changJia        = 3

class User(db.Model):
    __talbename__ = 'user_table'
    id          = db.Column(db.Integer, primary_key=True, autoincrement=True)
    userName    = db.Column(db.String(80), unique=True, nullable=False)
    passWord    = db.Column(db.String(80), nullable=False)
    phone       = db.Column(db.String(80))
    email       = db.Column(db.String(80), unique=True)
    userType    = db.Column(db.Enum(UserType))
    code        = db.Column(db.String(80), unique=True)
    pushToken   = db.Column(db.String(80))
    token       = db.Column(db.String(80))
    regiserType = db.Column(db.Integer, unique=True)
    userMoney   = db.Column(db.Float)

    def __init__(self, username, password, phone = None, email = None, code = None, pushToken = None, userType = 0, registerType = 0, userMoney = 0.0):
        self.userName = username
        self.passWord = password
        self.phone = phone
        self.email = email
        self.code = code
        self.pushToken = pushToken
        self.userType = userType
        self.regiserType = registerType
        self.userMoney = userMoney

db.create_all()
db.session.commit()


if __name__ == '__main__':
    app.run(debug = True)

when i run i meet this error:

Traceback (most recent call last):
  File "C:\Users\elqstux\workspace\Kaka\server.py", line 41, in <module>
    db.create_all()
  File "C:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py", line 972, in create_all
    self._execute_for_all_tables(app, bind, 'create_all')
  File "C:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py", line 964, in _execute_for_all_tables
    op(bind=self.get_engine(app, bind), **extra)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\schema.py", line 3745, in create_all
    tables=tables)
  File "C:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 1856, in _run_visitor
    conn._run_visitor(visitorcallable, element, **kwargs)
  File "C:\Python27\lib\site-packages\sqlalchemy\engine\base.py", line 1481, in _run_visitor
    **kwargs).traverse_single(element)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\visitors.py", line 121, in traverse_single
    return meth(obj, **kw)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\ddl.py", line 720, in visit_metadata
    _ddl_runner=self)
  File "C:\Python27\lib\site-packages\sqlalchemy\event\attr.py", line 256, in __call__
    fn(*args, **kw)
  File "C:\Python27\lib\site-packages\sqlalchemy\util\langhelpers.py", line 546, in __call__
    return getattr(self.target, self.name)(*arg, **kw)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\sqltypes.py", line 1038, in _on_metadata_create
    t = self.dialect_impl(bind.dialect)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\type_api.py", line 361, in dialect_impl
    return self._dialect_info(dialect)['impl']
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\type_api.py", line 403, in _dialect_info
    impl = self._gen_dialect_impl(dialect)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\type_api.py", line 412, in _gen_dialect_impl
    return dialect.type_descriptor(self)
  File "C:\Python27\lib\site-packages\sqlalchemy\engine\default.py", line 359, in type_descriptor
    return sqltypes.adapt_type(typeobj, self.colspecs)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\type_api.py", line 1186, in adapt_type
    return typeobj.adapt(impltype)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\sqltypes.py", line 1181, in adapt
    **kw)
  File "C:\Python27\lib\site-packages\sqlalchemy\dialects\mysql\base.py", line 1486, in __init__
    values, length = self._init_values(enums, kw)
  File "C:\Python27\lib\site-packages\sqlalchemy\dialects\mysql\base.py", line 1401, in _init_values
    q = e[0]
  File "C:\Python27\lib\site-packages\enum\__init__.py", line 393, in __getitem__
    return cls._member_map_[name]
KeyError: 0

According to documentation, if you have duplicate property names in child model, properties will have columns duplicated.

For example, if you do your models like this it'll work with joined inheritance, as there are no naming conflicts and SQLAlchemy does not have to map two columns into one property::

class Parent(db.Model):
    __tablename__ = 'parent'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
    type = db.Column(db.String(50))

    __mapper_args__ = {
        'polymorphic_identity': 'base',
        'polymorphic_on': type
    }

class Child(Parent):
    __tablename__ = 'child'
    child_id = db.Column(db.Integer, db.ForeignKey('parent.id'), primary_key=True)
    text = db.Column(db.String(50))

    __mapper_args__ = {
        'polymorphic_identity': 'child',
    }

And use this view for child model to prevent 'type' field being exposed in forms

class PolyModel(sqlamodel.ModelView): excluded_form_columns = ('type',)

With concrete inheritance it will just work without any problems.

I might think how to handle multi-column IDs, but can't provide any estimation right now.

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM