我最近开始使用Flask作为我的后端框架。但是,最近我遇到了一个问题,我无法弄清楚如何解决它。作为最后的手段,我想在这里尝试我的改变。如果你可以帮助我,我将不胜感激。
所以,我有一个继承自SQLAlchemy的db.Model的类:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
...
我想创建自己的Meta类来自动将一些Mixins插入到这个类中:
class MyMetaClass(type):
def __new__(meta, name, bases, class_dict):
bases += (Mixin1, Mixin2, Mixin3)
return type.__new__(meta, name, bases, class_dict)
但是,当我尝试将此Meta类与User类一起使用时:
class User(db.Model, metaclass=MyMetaClass):
...
我有以下错误:
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
有人知道如何解决这个问题吗?任何帮助,将不胜感激。
(注意:我不是Flask和Meta课程的大师。所以,如果我理解错误,请原谅我缺乏理解)
最后我设法解决了我的问题。如果其他人遇到同样的问题,我在这里发布一个解决方案。
这是一张来自SQLAlchemy's website的剪辑:
模型元类负责在定义模型子类时设置SQLAlchemy内部。 Flask-SQLAlchemy通过mixin添加了一些额外的行为;它的默认元类DefaultMeta继承了它们。
您可以通过定义自己的元类并自己创建声明性基础来添加自己的行为。一定要继承你想要的mixin(或者只是继承默认的元类)。
如上所示,将声明性基类而不是简单模型基类传递给base_class将导致Flask-SQLAlchemy使用此基础而不是使用默认元类构造基类。
from flask_sqlalchemy import SQLAlchemy
from flask_sqlalchemy.model import DefaultMeta, Model
class CustomMeta(DefaultMeta):
def __init__(cls, name, bases, d):
# custom class setup could go here
# be sure to call super
super(CustomMeta, cls).__init__(name, bases, d)
# custom class-only methods could go here
db = SQLAlchemy(model_class=declarative_base(
cls=Model, metaclass=CustomMeta, name='Model'))
您还可以传递您想要声明的所有其他参数declarative_base()以根据需要自定义基类。
除此之外,我最初的目的实际上是为我的模型添加一些额外的功能,这些功能继承自db.Model。实际上,您不需要使用Meta类。因此,对于这种情况,我们可以扩展db.Model类,如同一个网页中所述。这是为每个模型提供整数主键或连接表继承的外键的示例:
from flask_sqlalchemy import Model, SQLAlchemy
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declared_attr, has_inherited_table
class IdModel(Model):
@declared_attr
def id(cls):
for base in cls.__mro__[1:-1]:
if getattr(base, '__table__', None) is not None:
type = sa.ForeignKey(base.id)
break
else:
type = sa.Integer
return sa.Column(type, primary_key=True)
db = SQLAlchemy(model_class=IdModel)
class User(db.Model):
name = db.Column(db.String)
class Employee(User):
title = db.Column(db.String)