defer_except.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import six
  2. from sqlalchemy import inspect
  3. from sqlalchemy.orm import defer
  4. from sqlalchemy.orm.properties import ColumnProperty
  5. from sqlalchemy.orm.query import _ColumnEntity
  6. from sqlalchemy.orm.mapper import Mapper
  7. def property_names(properties):
  8. names = []
  9. for property_ in properties:
  10. if isinstance(property_, six.string_types):
  11. names.append(property_)
  12. else:
  13. names.append(
  14. '%s.%s' % (
  15. property_.class_.__name__,
  16. property_.key
  17. )
  18. )
  19. return names
  20. def query_entities(query):
  21. entities = []
  22. for entity in query._entities:
  23. if not isinstance(entity, _ColumnEntity):
  24. entities.append(entity.entity_zero.class_)
  25. for entity in query._join_entities:
  26. if isinstance(entity, Mapper):
  27. entities.append(entity.class_)
  28. else:
  29. entities.append(entity)
  30. return entities
  31. def defer_except(query, columns):
  32. """
  33. Deferred loads all columns in given query, except the ones given.
  34. This function is very useful when working with models with myriad of
  35. columns and you want to deferred load many columns.
  36. >>> from sqlalchemy_utils import defer_except
  37. >>> query = session.query(Article)
  38. >>> query = defer_except(Article, [Article.id, Article.name])
  39. :param columns: columns not to deferred load
  40. """
  41. model = query._entities[0].entity_zero.class_
  42. for property_ in inspect(model).attrs:
  43. if isinstance(property_, ColumnProperty):
  44. column = property_.columns[0]
  45. if column.name not in columns:
  46. query = query.options(defer(property_.key))
  47. return query