Python 编辑主键具有枚举的记录时发生Flask admin错误

Python 编辑主键具有枚举的记录时发生Flask admin错误,python,postgresql,flask-sqlalchemy,flask-admin,Python,Postgresql,Flask Sqlalchemy,Flask Admin,使用postgres并尝试编辑包含枚举的主键的记录将出现错误 这是因为ID包含枚举的类名,即MyEnum..ONE,而它应该仅为ONE: test.py 从枚举导入枚举 从烧瓶进口烧瓶 从flask_admin导入admin 从flask_admin.contrib.sqla导入模型视图 从flask_sqlalchemy导入sqlalchemy 从sqlalchemy导入PrimaryKeyConstraint app=烧瓶(名称) app.config['SQLALCHEMY\u DATA

使用postgres并尝试编辑包含枚举的主键的记录将出现错误

这是因为ID包含枚举的类名,即
MyEnum..ONE
,而它应该仅为
ONE

test.py

从枚举导入枚举
从烧瓶进口烧瓶
从flask_admin导入admin
从flask_admin.contrib.sqla导入模型视图
从flask_sqlalchemy导入sqlalchemy
从sqlalchemy导入PrimaryKeyConstraint
app=烧瓶(名称)
app.config['SQLALCHEMY\u DATABASE\u URI']='postgresql://'
app.config['SQLALCHEMY_ECHO']=True
db=SQLAlchemy(应用程序)
MyEnum类(枚举):
一=1
类MyModel(db.Model):
id=db.Column(db.Integer)
enum=db.Column(db.enum(MyEnum))
__表参数=(
PrimaryKeyConstraint('id','enum',name='pk_mymodel'),
)
类MyAdminView(模型视图):
列\显示\主键=真
admin=admin(应用程序)
admin.add_视图(MyAdminView(MyModel,db.session))
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
#启动应用程序
db.drop_all()
db.create_all()
添加(MyModel(id=1,enum=MyEnum.ONE))
db.session.commit()
app.run(debug=True)
使用
python test.py运行,然后转到并单击编辑记录:


这是因为
flask\u admin
如何在URL中为给定实例构建主键值

在玩了一段时间调试器并深入研究之后,我发现这是因为
MyModel
实例上
enum
属性的字符串表示实际上等于
'MyEnum.ONE'

str(my_model_instance.enum)==“MyEnum.ONE”

str
最终被which调用which被which调用which被which调用which被which调用结果在管理模板的url中使用

在下一个版本中,在他们可能修复此问题之前,您可以覆盖MyEnum的
\uuu str\uuu
方法,以便返回其名称,然后返回
str(my\u model\u instance.enum)==“ONE”

class MyEnum(Enum):
    ONE = 1

    def __str__(self):
        return self.name
现在编辑的url是:
正如所料。

这是因为
flask\u admin
如何在URL中为给定实例构建主键值

在玩了一段时间调试器并深入研究之后,我发现这是因为
MyModel
实例上
enum
属性的字符串表示实际上等于
'MyEnum.ONE'

str(my_model_instance.enum)==“MyEnum.ONE”

str
最终被which调用which被which调用which被which调用which被which调用结果在管理模板的url中使用

在下一个版本中,在他们可能修复此问题之前,您可以覆盖MyEnum的
\uuu str\uuu
方法,以便返回其名称,然后返回
str(my\u model\u instance.enum)==“ONE”

class MyEnum(Enum):
    ONE = 1

    def __str__(self):
        return self.name
现在编辑的url是:
正如预期的那样。

如果您不想覆盖MyEnum的
\u str\u
方法,您可以覆盖MyAdminView的
get\u pk\u value
方法,以便为flask admin构建正确的主键值

from enum import Enum
from flask import Flask
from flask_admin import Admin,tools
from flask_admin.contrib.sqla import ModelView
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import PrimaryKeyConstraint

class MyAdminView(ModelView):
    column_display_pk = True
    form_columns = ('id', 'enum')

    def get_pk_value(self, model):
        if isinstance(self._primary_key, tuple):
            pk_values = []
            for attr in self._primary_key:
                value = getattr(model, attr)
                if type(value) is MyEnum:
                    pk_values.append(value.name)
                else:
                    pk_values.append(value)
            return tools.iterencode(pk_values)
        else:
            return tools.escape(getattr(model, self._primary_key))
现在编辑的url是:
/admin/mymodel/edit/?id=1%2CONE&url=%2Fadmin%2Fmymodel%2F

正如预期的那样。

如果您不想覆盖MyEnum的
\u str\u
方法,您可以覆盖MyAdminView的
get\u pk\u value
方法,以便为flask admin构建正确的主键值

from enum import Enum
from flask import Flask
from flask_admin import Admin,tools
from flask_admin.contrib.sqla import ModelView
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import PrimaryKeyConstraint

class MyAdminView(ModelView):
    column_display_pk = True
    form_columns = ('id', 'enum')

    def get_pk_value(self, model):
        if isinstance(self._primary_key, tuple):
            pk_values = []
            for attr in self._primary_key:
                value = getattr(model, attr)
                if type(value) is MyEnum:
                    pk_values.append(value.name)
                else:
                    pk_values.append(value)
            return tools.iterencode(pk_values)
        else:
            return tools.escape(getattr(model, self._primary_key))
现在编辑的url是:
/admin/mymodel/edit/?id=1%2CONE&url=%2Fadmin%2Fmymodel%2F

正如所料。

感谢您对此进行调查。这是我使用的解决方法,但我希望有一种替代方法来覆盖
\uuuu str\uuuu
。感谢您对此进行研究。这是我使用的解决方法,但我希望有一种替代方法来覆盖
\uu str\uu