Skip to content

Support for hybrid_property? #15

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

Closed
gsvitak opened this issue Oct 17, 2016 · 12 comments
Closed

Support for hybrid_property? #15

gsvitak opened this issue Oct 17, 2016 · 12 comments

Comments

@gsvitak
Copy link

gsvitak commented Oct 17, 2016

Hello,

I am trying to use hybrid_property as a property on a GraphQL response. However, when I execute the GraphQL request, I am receiving an error stating the property cannot be found.

Are SQlAlchemy hybrid_property attributes currently supported?

Thanks,
G

@hybrid_property
    def document_count(self):
        return len(self.linked_documents)
@kvey
Copy link
Contributor

kvey commented Dec 8, 2016

Looking into this and the main issue I see atm is what type the value of hybrid_property will have? Columns and relationships the types can be determined by their definitions, but hybrid_property is dynamic.

Graphene does have a dynamic property - looking into that.

https://github.com/kvey/graphene-sqlalchemy/tree/feature/support-hybrid-property wip

One way to solve the type issue is to rely on type annotations on the hybrid_property, but that'd depend on python3. Not sure what an actual solution is if anyone has any ideas.

@gsvitak
Copy link
Author

gsvitak commented Dec 8, 2016

Thanks..

How I worked around the problem was that I had to explicitly declare the GraphQl type via the hybrid method name in the schema and then make sure the SQLAlchemy returned the exact type in the hybrid method. Works for now.. but it would be great if the SQLAlchemy could handle automatically.

@syrusakbary
Copy link
Member

This is now fixed in master (and upcoming version 2.0). Closing the issue

@anisjonischkeit
Copy link

anisjonischkeit commented Feb 20, 2018

My hybrid property always returns a list of SQLAlchemy objects, how can I let graphene-sqlalchemy know about this so it doesn't just return a string (so it can return the appropriate SQLAlchemyObjectType)? Also I am using python2

@gsvitak
Copy link
Author

gsvitak commented Feb 20, 2018

Can you please provide a sample. Might be easier.

@anisjonischkeit
Copy link

# models.py

class Company(Base):
    __tablename__ = 'licence_revisions'

    id = Column(...)
    ...

    licence_states = relationship("Licence", back_populates="company", lazy="dynamic")

    @hybrid_property
    def latest_licence_states(self):
        db_session = object_session(self)

        return self.licence_states \
                   .order_by(Licence.uuid, Licence.revision_id) \
                   .distinct(Licence.uuid).all()

# query.py

class Licence(SQLAlchemyObjectType):
    ...

class Company(SQLAlchemyObjectType):
    class Meta:
        model = models.Company
        interfaces = (graphene.relay.Node, )


    # currently I need these lines to get it to work properly. if I leave them out I
    # just get a string representation of the list of  SQLAlchemy objects:
    # "[<models.Licence object at 0x7f073450ba90>, <models.Licence object at 0x7f073450bb10>]"

    latest_licence_states = SQLAlchemyConnectionField(Licence)
    def resolve_latest_licence_states(self, info):
        return self.latest_licence_states

class Query(graphene.ObjectType):
    node = graphene.relay.Node.Field()

    Company = graphene.Field(Company)
    def resolve_company(self, info):

        query = info.context["session"].query
        company = query(models.Company).get(COMPANY_ID)

        return company

I want to tell graphene-sqlalchemy that the returned type for the hybrid_property is a list of SQLAlchemy objects

@Salamek
Copy link
Contributor

Salamek commented Apr 7, 2021

@anisjonischkeit Just probably late answer to your Q (and help anyone who google this as i did), i had similar problem with hybrid property that returned boolean, but graphene-sqlalchemy was casting it to string ("true" instead of true).
Only thing i had to do is set query return type in SQLAlchemyObjectType is_managed = graphene.Boolean():

class Subject(SQLAlchemyObjectType):
    # is_managed is hybrid property so we need to force the type
    is_managed = graphene.Boolean()

    class Meta:
        model = SubjectModel
        interfaces = (relay.Node, )

After this i get correct is_managed: true instead of is_managed: "true" in query response JSON

Not sure if this fix can help with your problem or not, but i guess you should use something like graphene.List(Licence)

@lkaupp
Copy link

lkaupp commented Jun 23, 2021

@Salamek this should be mentioned in the official docs if using the hybrid property. Works like a charm!

Here some example code for graphene-flask-sqlalchemy for beginners - just for documentation:

//models/__init__.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
//model.py
from sqlalchemy.ext.hybrid import hybrid_property
from backend.server.models import db

class CurrentListening(db.Model):
    __tablename__ = 'current_listening'
    id = db.Column(db.Integer, primary_key=True)
    depth = db.Column(db.Integer)
    _listening_endpoints = db.Column('listening_endpoints', db.String(), nullable=False, default='[]', server_default='[]')

    @hybrid_property
    def listening_endpoints(self):
        return json.loads(self._listening_endpoints)

    @listening_endpoints.setter
    def listening_endpoints(self, listening_endpoints):
        self._listening_endpoints = json.dumps(listening_endpoints)

//schema.py
class Listening(SQLAlchemyObjectType):
    class Meta:
        model = CurrentListening
        interfaces = (relay.Node, )

    listening_endpoints = graphene.List(graphene.String)

class ListeningQuery(graphene.ObjectType):
    listenings = SQLAlchemyConnectionField(Listening.connection)

@flipbit03
Copy link
Contributor

flipbit03 commented Apr 28, 2022

It'd be very nice if the hybrid_property translator could use something like the function's return type hints as the actual base for generating the final GraphQL type, so that we don't need to override the type in the final generated GraphQL object.

@erikwrede
Copy link
Member

@flipbit03 check out #333

@flipbit03
Copy link
Contributor

I have opened a pull request for this in #340, satisfying most use cases with the types in the Standard Library and the List[T] container type. It also includes the ability to retrieve a previously generated SQLAlchemyObjectType.

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related topics referencing this issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants