-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for hybrid_property
fields?
#30
Comments
Hybrid property is not supported at this time. I'll try to add support. |
Done! New release. Example: models.py, filters.py
|
Awesome! I will test this out! |
I tried this out on the latest version but I'm getting this error when including the hybrid property field
|
Are you doing the correct sqlalchemy hybrid_property? Can you provide an example for getting this error? |
Below is full running example that generates the error: from sqlalchemy import Column, ForeignKey, Integer, String, create_engine
from sqlalchemy.orm import relationship, scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
import graphene
from graphene import Connection, Node
from graphene_sqlalchemy import SQLAlchemyObjectType
from graphene_sqlalchemy_filter import FilterableConnectionField, FilterSet
Base = declarative_base()
class PostModel(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"))
name = Column(String(255))
user = relationship("UserModel", back_populates="posts")
@hybrid_property
def status(self):
return "SUBMITTED"
class UserModel(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(255))
posts = relationship("PostModel", back_populates="user")
class PostFilter(FilterSet):
class Meta:
model = PostModel
fields = {
"name": [...],
"status": ["eq"]
}
class MyFilterableConnectionField(FilterableConnectionField):
filters = {PostModel: PostFilter()}
class UserNode(SQLAlchemyObjectType):
class Meta:
model = UserModel
interfaces = (Node,)
connection_field_factory = MyFilterableConnectionField.factory
class UserConnection(Connection):
class Meta:
node = UserNode
class PostNode(SQLAlchemyObjectType):
class Meta:
model = PostModel
interfaces = (Node,)
connection_field_factory = MyFilterableConnectionField.factory
class PostConnection(Connection):
class Meta:
node = PostNode
class Query(graphene.ObjectType):
user = graphene.relay.Node.Field(UserNode)
all_users = MyFilterableConnectionField(UserConnection)
post = graphene.relay.Node.Field(PostNode)
all_posts = MyFilterableConnectionField(PostConnection)
schema = graphene.Schema(query=Query)
engine = create_engine('sqlite://', echo=True) # in-memory
db_session = scoped_session(sessionmaker(bind=engine))
Base.query = db_session.query_property()
Base.metadata.create_all(bind=engine)
db_session.commit()
result = schema.execute('query {allPosts (filters: {status: "SUBMITTED"}) { edges { node { id } } } }')
print(result) Full Traceback:
|
Can you test new release? |
I tested the new release with the code I posted above and it works. I added some logic to the hybrid_property attribute, however, and encountered some strange results. It seems as if when I add conditionals to hybrid_property based on the values of other columns it is now treating the boolean value of the referenced column as true always. To demonstrate I modified the above code with: @hybrid_property
def status(self):
if self.name:
return "NAMED"
return "UNNAMED" And added a user and post to the database... user = UserModel(username="aUser")
db_session.add(user)
db_session.add(PostModel(user_id=user.id))
db_session.commit() But when querying result = schema.execute('query {allPosts (filters: {status: "NAMED"}) { edges { node { id name status } } } }') I get this result: {"data": {"allPosts": {"edges": [{"node": {"id": "UG9zdE5vZGU6MQ==", "name": null, "status": "UNNAMED"}}]}}} Clearly the column's comparison operation is evaluated properly by the hybrid_property on query (hence why it shows "UNNAMED" in the json), but it is not evaluated correctly when filtered. |
Your hybrid_property has a logic error. try update your code like this @hybrid_property
def status(self):
print(self.name, type(self.name), bool(self.name))
if self.name:
return "NAMED"
return "UNNAMED" upon execution you get To solve this problem, I recommend making a simple filter. |
Shouldn't an I can look into simple filter as a different implementation strategy. |
Filtering is performed for insertion into a database query. The hybrid property value is calculated after the database query is executed. |
That makes more sense. Thanks for pointing out that |
I tried using the
FilterSet
Class to create a filter on a field defined by ahybrid_property
in my sqlalchemy model, but it seems to have no effect. Graphene-Sqlalchemy does resolve the field on the type, but thefilters
argument does not accept thehybrid_property
field I defined. I tried both the shortcut[...]
as well as explicit filter types but neither worked. Is this supported?Here's an example (overly simplified for clarity):
models.py
filters.py
schema.py
Running this query:
Returns:
The text was updated successfully, but these errors were encountered: