如何设置graphene-sqlalchemy来按ID过滤对象?
我想运行查询:
{
marker(markerId: 1) {
markerId
title
}
}
我希望得到一个Marker对象,其中markerId为1,但我得到错误“Unknown argument”markerId“on field”mark“of type”Query“。”
我有两个文件:
schema.py
import graphene
from graphene_sqlalchemy import SQLAlchemyObjectType
from model import db_session, Marker as MarkerModel
class Marker(SQLAlchemyObjectType):
class Meta:
model = MarkerModel
class Query(graphene.ObjectType):
marker = graphene.Field(Marker)
markers = graphene.List(Marker)
def resolve_markers(self, args, context, info):
return db_session.query(MarkerModel).all()
def resolve_marker(self, args, context, info):
return db_session.query(MarkerModel).first()
schema = graphene.Schema(query=Query)
model.py
import sqlalchemy as db
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from instance.config import settings
engine = db.create_engine(settings["SQLALCHEMY_DATABASE_URI"])
sm = sessionmaker(bind=engine)
db_session = scoped_session(sm)
Base = declarative_base()
Base.query = db_session.query_property()
class Marker(Base):
__tablename__ = "marker"
marker_id = db.Column(db.Integer, primary_key=True)
latitude = db.Column(db.Float)
longitude = db.Column(db.Float)
title = db.Column(db.String(100))
blurb = db.Column(db.String(65535))
def __repr__(self):
return "<Marker %d: %s>".format([self.marker_id, self.title])
感谢您的帮助!
答案 0 :(得分:0)
我没有使用过sql-alchemy,但我想你必须为你的模型添加Node接口,如:
class Marker(SQLAlchemyObjectType):
class Meta:
model = MarkerModel
interfaces = (Node,)
答案 1 :(得分:0)
可以在https://github.com/somada141/demo-graphql-sqlalchemy-falcon下找到完整的工作演示。
考虑以下SQLAlchemy ORM类:
class Author(Base, OrmBaseMixin):
__tablename__ = "authors"
author_id = sqlalchemy.Column(
sqlalchemy.types.Integer(),
primary_key=True,
)
name_first = sqlalchemy.Column(
sqlalchemy.types.Unicode(length=80),
nullable=False,
)
name_last = sqlalchemy.Column(
sqlalchemy.types.Unicode(length=80),
nullable=False,
)
简单地用SQLAlchemyObjectType
包裹:
class TypeAuthor(SQLAlchemyObjectType):
class Meta:
model = Author
并透露:
author = graphene.Field(
TypeAuthor,
author_id=graphene.Argument(type=graphene.Int, required=False),
name_first=graphene.Argument(type=graphene.String, required=False),
name_last=graphene.Argument(type=graphene.String, required=False),
)
@staticmethod
def resolve_author(
args,
info,
author_id: Union[int, None] = None,
name_first: Union[str, None] = None,
name_last: Union[str, None] = None,
):
query = TypeAuthor.get_query(info=info)
if author_id:
query = query.filter(Author.author_id == author_id)
if name_first:
query = query.filter(Author.name_first == name_first)
if name_last:
query = query.filter(Author.name_last == name_last)
author = query.first()
return author
GraphQL查询,例如:
query GetAuthor{
author(authorId: 1) {
nameFirst
}
}
将产生回应:
{
"data": {
"author": {
"nameFirst": "Robert"
}
}
}
如您所见,您可以在graphene.Argument
实例化期间通过graphene.Field
类传递命名参数,这也必须在解析器方法中命名。但是,两者的结合使您可以进行各种过滤。
答案 2 :(得分:0)
石墨烯中继。在这种情况下,ID将是中继节点ID,您可以根据ID的需要进行更改。
您可以在下面的链接中找到一个不错的例子:
答案 3 :(得分:0)
定义查询时,需要指定marker_id
作为查询参数。
...
class Query(graphene.ObjectType):
marker = graphene.Field(Marker, marker_id=graphene.String())
markers = graphene.List(Marker)
def resolve_markers(self, args, context, info):
return db_session.query(MarkerModel).all()
def resolve_marker(self, args, context, info, marker_id):
return db_session.query(MarkerModel).filter(MarkerModel.id == marker_id).first()
...
答案 4 :(得分:0)
一种用于石墨烯过滤的通用解决方案。在网上阅读了大量评论后,我做了这个 -
考虑这是您的对象,它引用了一个名为 Post
class PostObject(SQLAlchemyObjectType):
class Meta:
model = Post
interfaces = (graphene.relay.Node, )
然后对于查询:
class Query(graphene.ObjectType):
node = graphene.relay.Node.Field()
all_posts = FilteredConnectionField(PostObject)
在单独的文件中将其作为类编写
import graphene
import sqlalchemy
from graphene_sqlalchemy import SQLAlchemyConnectionField
class FilteredConnectionField(SQLAlchemyConnectionField):
def __init__(self, type, *args, **kwargs):
fields = {}
columns = input_type._meta.model.__table__.c
for col in columns:
fields[col.name] = self.sql_graphene_type_mapper(col.type)
kwargs.update(fields)
super().__init__(type, *args, **kwargs)
@classmethod
def get_query(cls, model, info, sort=None, **args):
query = super().get_query(model, info, sort=sort, **args)
omitted = ('first', 'last', 'hasPreviousPage', 'hasNextPage', 'startCursor', 'endCursor')
for name, val in args.items():
if name in omitted: continue
col = getattr(model, name, None)
if col:
query = query.filter(col == val)
return query
def sql_graphene_type_mapper(self, col_type):
if isinstance(col_type, sqlalchemy.Integer): return graphene.Int()
elif isinstance(col_type, sqlalchemy.Boolean): return graphene.Boolean()
elif isinstance(col_type, sqlalchemy.DateTime): return graphene.types.DateTime()
elif isinstance(col_type, (sqlalchemy.FLOAT, sqlalchemy.BIGINT, sqlalchemy.NUMERIC )): return graphene.Float()
else:
return graphene.String()
我希望这门课可以帮助其他人。
如果您在线搜索并浏览石墨烯 converter.py
文件,可以找到更多实例类型转换映射。