Graphene_sqlalchemy 和flask-sqlalchemy 对于有效 SQLAlchemy 模型的构成存在分歧?

问题描述 投票:0回答:3

在使用 Flask、Graphene 时遇到了问题。考虑以下。

模型项目.model.site:

from project import db
from project.models import user
from datetime import datetime

class Site(db.Model):
    __tablename__ = 'sites'
    id = db.Column(db.Integer(), primary_key=True)
    owner_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    name = db.Column(db.String(50))
    desc = db.Column(db.Text())
    location_lon = db.Column(db.String(50))
    location_lat = db.Column(db.String(50))
    creation_date = db.Column(db.DateTime(), default=datetime.utcnow())
    users = db.relationship(
        user,
        backref=db.backref('users',
                        uselist=True,
                        cascade='delete,all'))

模型架构(project.schemas.site_schema)

from graphene_sqlalchemy import SQLAlchemyObjectType
from project.models import site as site_model
import graphene

class SiteAttributes:
    owner_id = graphene.ID(description="Site owners user.id")
    name = graphene.String(description="Site Name")
    desc = graphene.String(description="Site description")
    location_lon = graphene.String(description="Site Longitude")
    location_lat = graphene.String(description="Site Latitude")
    creation_date = graphene.DateTime(description="Site Creation Date")

class Site(SQLAlchemyObjectType, SiteAttributes):
    """Site node."""
    class Meta:
        model = site_model
        interfaces = (graphene.relay.Node,)

最后是我计划公开 GraphQL api (project.schemas.schema)) 的主模式

from graphene_sqlalchemy import SQLAlchemyConnectionField
import graphene
from project.schemas import site_schema, trade_schema, user_schema

class Query(graphene.ObjectType):
    """Query objects for GraphQL API."""

    node = graphene.relay.Node.Field()
    user = graphene.relay.Node.Field(user_schema.User)
    userList = SQLAlchemyConnectionField(user_schema.User)
    site = graphene.relay.Node.Field(site_schema.Site)
    siteList = SQLAlchemyConnectionField(site_schema.Site)
    trade = graphene.relay.Node.Field(trade_schema.Trade)
    tradeList = SQLAlchemyConnectionField(trade_schema.Trade)


schema = graphene.Schema(query=Query)

如果我在启动时加载模型,一切都很好。迁移发生,应用程序运行得很好。如果我通过架构加载模型,但应用程序会失败并显示以下消息:

AssertionError: You need to pass a valid SQLAlchemy Model in Site.Meta, received "<module 'project.models.site' from '/vagrant/src/project/models/site.py'>".

我用flask_sqlalchemy初始化了SQLAlchemy。这让我想知道创建的模型是否不被视为有效的 SQLAlchemy 模型?或者我在这里犯了一个我没有看到的基本错误。我假设是后者。

python flask flask-sqlalchemy graphene-sqlalchemy
3个回答
4
投票

根据错误消息,似乎

project.models.site
(在第二个片段中使用
from project.models import site as site_model
导入)是一个 Python 模块,而不是
db.Model
或类似模块的子类。您是否想导入
Site
(大写)而不是
site


1
投票

因此,将包修复到类中最终让我朝着正确的方向前进。事实证明,问题比这更深刻。实现这一点的唯一方法是阅读隐藏的异常。

首先,我确保加载的是实际模型而不是模块。非常感谢你@jwodder

最终这https://github.com/graphql-python/graphene-sqlalchemy/issues/121最终为我指明了正确的方向。通过检查实际的异常消息,我找到了解决方案


0
投票

我发现这是由于graphene_sqlalchemy源代码中的这个断言造成的:(位于

graphene_sqlalchemy/types.py

assert is_mapped_class(model), (
    "You need to pass a valid SQLAlchemy Model in " '{}.Meta, received "{}".'
).format(cls.__name__, model)

当转到

is_mapped_class
功能时:(可在:
graphene_sqlalchemy/utils.py

def is_mapped_class(cls):
    try:
        class_mapper(cls)
    except (ArgumentError, UnmappedClassError):
        return False
    else:
        return True

我在

class_mapper(cls)
处设置了一个断点,该断点打印了实际出错的地方。这与以下事情有关:

sqlalchemy.exc.InvalidRequestError: Mapper 'mapped class Foo->FOO' has no property 'bar'
© www.soinside.com 2019 - 2024. All rights reserved.