Fix sort_query aliased hybrid_property handling

This commit is contained in:
Konsta Vesterinen
2014-07-29 14:01:58 +03:00
parent 051191f671
commit ca3257b1cc
7 changed files with 79 additions and 13 deletions

View File

@@ -4,6 +4,12 @@ Changelog
Here you can see the full list of changes between each SQLAlchemy-Utils release.
0.26.7 (2014-07-29)
^^^^^^^^^^^^^^^^^^^
- Made sort_query support hybrid properties where function name != property name
0.26.6 (2014-07-22)
^^^^^^^^^^^^^^^^^^^

View File

@@ -44,7 +44,7 @@ for name, requirements in extras_require.items():
setup(
name='SQLAlchemy-Utils',
version='0.26.6',
version='0.26.7',
url='https://github.com/kvesteri/sqlalchemy-utils',
license='BSD',
author='Konsta Vesterinen, Ryan Leckey, Janne Vanhala, Vesa Uimonen',

View File

@@ -15,6 +15,7 @@ from .functions import (
get_column_key,
get_columns,
get_declarative_base,
get_hybrid_properties,
get_mapper,
get_primary_keys,
get_referencing_foreign_keys,
@@ -73,7 +74,7 @@ from .types import (
from .models import Timestamp
__version__ = '0.26.6'
__version__ = '0.26.7'
__all__ = (
@@ -96,6 +97,7 @@ __all__ = (
get_column_key,
get_columns,
get_declarative_base,
get_hybrid_properties,
get_mapper,
get_primary_keys,
get_referencing_foreign_keys,

View File

@@ -23,6 +23,7 @@ from .orm import (
get_column_key,
get_columns,
get_declarative_base,
get_hybrid_properties,
get_mapper,
get_primary_keys,
get_tables,
@@ -46,6 +47,7 @@ __all__ = (
'get_bind',
'get_columns',
'get_declarative_base',
'get_hybrid_properties',
'get_mapper',
'get_primary_keys',
'get_referencing_foreign_keys',

View File

@@ -416,10 +416,55 @@ def get_attrs(expr):
return inspect(expr).attrs
def get_hybrid_properties(class_):
for prop in sa.inspect(class_).all_orm_descriptors:
if isinstance(prop, hybrid_property):
yield prop
def get_hybrid_properties(model):
"""
Returns a dictionary of hybrid property keys and hybrid properties for
given SQLAlchemy declarative model / mapper.
Consider the following model
::
from sqlalchemy.ext.hybrid import hybrid_property
class Category(Base):
__tablename__ = 'category'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
@hybrid_property
def lowercase_name(self):
return self.name.lower()
@lowercase_name.expression
def lowercase_name(cls):
return sa.func.lower(cls.name)
You can now easily get a list of all hybrid property names
::
from sqlalchemy_utils import get_hybrid_properties
get_hybrid_properties(Category).keys() # ['lowercase_name']
.. versionchanged: 0.26.7
This function now returns a dictionary instead of generator
:param model: SQLAlchemy declarative model or mapper
"""
return dict(
(key, prop)
for key, prop in sa.inspect(model).all_orm_descriptors.items()
if isinstance(prop, hybrid_property)
)
def get_expr_attr(expr, attr_name):
@@ -483,10 +528,10 @@ def getdotattr(obj_or_class, dot_path):
def has_changes(obj, attrs=None, exclude=None):
"""
Simple shortcut function for checking if given attribute(s) of given
declarative model object has changed during the transaction. Without
Simple shortcut function for checking if given attributes of given
declarative model object have changed during the session. Without
parameters this checks if given object has any modificiations. Additionally
exclude parameter can be given which check if given object has any changes
exclude parameter can be given to check if given object has any changes
in any attributes other than the ones given in exclude.
@@ -552,7 +597,7 @@ def has_changes(obj, attrs=None, exclude=None):
)
def has_any_changes(model, columns):
def has_any_changes(obj, columns):
"""
Simple shortcut function for checking if any of the given attributes of
given declarative model object have changes.
@@ -580,7 +625,7 @@ def has_any_changes(model, columns):
:param obj: SQLAlchemy declarative model object
:param attrs: Names of the attributes
"""
return any(has_changes(model, column) for column in columns)
return any(has_changes(obj, column) for column in columns)
def identity(obj_or_class):

View File

@@ -59,8 +59,8 @@ class QuerySorter(object):
mapper = mapper.mapper
entity = mapper.entity
for prop in get_hybrid_properties(mapper):
if attr == prop.__name__:
for key in get_hybrid_properties(mapper).keys():
if attr == key:
return getattr(entity, attr)
def parse_sort_arg(self, arg):

View File

@@ -137,6 +137,17 @@ class TestSortQuery(TestCase):
) in str(query)
assert ' DESC' in str(query)
def test_assigned_hybrid_property(self):
def getter(self):
return self.name
self.Article.some_hybrid = sa.ext.hybrid.hybrid_property(
fget=getter
)
query = self.session.query(self.Article)
query = sort_query(query, 'some_hybrid')
assert 'ORDER BY article.name ASC' in str(query)
def test_relation_hybrid_property(self):
query = (
self.session.query(self.Article)