diff --git a/graphene_sqlalchemy/converter.py b/graphene_sqlalchemy/converter.py index c8170ba8..7b83d47f 100644 --- a/graphene_sqlalchemy/converter.py +++ b/graphene_sqlalchemy/converter.py @@ -11,7 +11,7 @@ from .fields import SQLAlchemyConnectionField try: - from sqlalchemy_utils import ChoiceType, JSONType, ScalarListType + from sqlalchemy_utils import ChoiceType, JSONType, ScalarListType, TSVectorType except ImportError: class ChoiceType(object): pass @@ -48,7 +48,10 @@ def dynamic_type(): return Field(List(_type)) return Dynamic(dynamic_type) - + +def convert_sqlalchemy_hybrid_method(hybrid_item): + return String(description=getattr(hybrid_item, '__doc__', None), + required=False) def convert_sqlalchemy_composite(composite, registry): converter = registry.get_converter_for_composite(composite.composite_class) @@ -97,6 +100,7 @@ def convert_sqlalchemy_type(type, column, registry=None): @convert_sqlalchemy_type.register(types.Enum) @convert_sqlalchemy_type.register(postgresql.ENUM) @convert_sqlalchemy_type.register(postgresql.UUID) +@convert_sqlalchemy_type.register(TSVectorType) def convert_column_to_string(type, column, registry=None): return String(description=get_column_doc(column), required=not(is_column_nullable(column))) diff --git a/graphene_sqlalchemy/types.py b/graphene_sqlalchemy/types.py index 70729ed6..199c9486 100644 --- a/graphene_sqlalchemy/types.py +++ b/graphene_sqlalchemy/types.py @@ -2,6 +2,7 @@ import six from sqlalchemy.inspection import inspect as sqlalchemyinspect +from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm.exc import NoResultFound from graphene import Field, ObjectType @@ -13,7 +14,8 @@ from .converter import (convert_sqlalchemy_column, convert_sqlalchemy_composite, - convert_sqlalchemy_relationship) + convert_sqlalchemy_relationship, + convert_sqlalchemy_hybrid_method) from .registry import Registry, get_global_registry from .utils import get_query, is_mapped @@ -47,6 +49,24 @@ def construct_fields(options): converted_composite = convert_sqlalchemy_composite(composite, options.registry) fields[name] = converted_composite + for hybrid_item in inspected_model.all_orm_descriptors: + + if type(hybrid_item) == hybrid_property: + name = hybrid_item.__name__ + + is_not_in_only = only_fields and name not in only_fields + is_already_created = name in options.fields + is_excluded = name in exclude_fields or is_already_created + + if is_not_in_only or is_excluded: + # We skip this field if we specify only_fields and is not + # in there. Or when we excldue this field in exclude_fields + + continue + converted_hybrid_property = convert_sqlalchemy_hybrid_method( + hybrid_item) + fields[name] = converted_hybrid_property + # Get all the columns for the relationships on the model for relationship in inspected_model.relationships: is_not_in_only = only_fields and relationship.key not in only_fields