[TurboGears] @paginateデコレータで並び順を指定する場合は、SQLAlchemyが必要である(たとえモデルにSQLObjectを使っていても)。

環境

この記事の内容は、TurboGears 1.0.1で確認しました。

現象

以下のような、default_order引数を含む@paginateデコレータをメソッドに付加します。

    @paginate(var_name="authors", max_pages=car.const.list_max_page,
        limit=car.const.list_limit, default_order="name")

すると、以下のような例外が発生します。

500 Internal error

The server encountered an unexpected condition which prevented it from fulfillin
g the request.   

Page handler: >   
Traceback (most recent call last):
  File "/usr/lib/python2.4/site-packages/CherryPy-2.2.1-py2.4.egg/cherrypy/_cpht
tptools.py", line 105, in _run
    self.main()  
  File "/usr/lib/python2.4/site-packages/CherryPy-2.2.1-py2.4.egg/cherrypy/_cpht
tptools.py", line 254, in main
    body = page_handler(*virtual_path, **self.params)
  File "", line 3, in index
  File "/usr/lib/python2.4/site-packages/TurboGears-1.0.1-py2.4.egg/turbogears/c
ontrollers.py", line 334, in expose
    output = database.run_with_transaction(
  File "", line 5, in run_with_transaction
  File "/usr/lib/python2.4/site-packages/TurboGears-1.0.1-py2.4.egg/turbogears/database.py", line 302, in so_rwt
    retval = func(*args, **kw)
  File "", line 5, in _expose
  File "/usr/lib/python2.4/site-packages/TurboGears-1.0.1-py2.4.egg/turbogears/controllers.py", line 351, in 
    mapping, fragment, args, kw)))
  File "/usr/lib/python2.4/site-packages/TurboGears-1.0.1-py2.4.egg/turbogears/controllers.py", line 378, in _execute_func
    output = errorhandling.try_call(func, *args, **kw)
  File "/usr/lib/python2.4/site-packages/TurboGears-1.0.1-py2.4.egg/turbogears/errorhandling.py", line 73, in try_call
    return func(self, *args, **kw)
  File "", line 3, in index
  File "/usr/lib/python2.4/site-packages/TurboGears-1.0.1-py2.4.egg/turbogears/paginate.py", line 75, in decorated
    order_by_expr = sql_order_col(col, order_opts[1])
  File "/usr/lib/python2.4/site-packages/TurboGears-1.0.1-py2.4.egg/turbogears/paginate.py", line 249, in sql_order_col
    if isinstance(col, sqlalchemy.schema.Column):
NameError: global name 'sqlalchemy' is not defined

対策

以下のようにして、SQLAlchemyをインストールします。

$ sudo easy_install sqlalchemy
Searching for sqlalchemy
Reading http://www.python.org/pypi/sqlalchemy/
Couldn't find index page for 'sqlalchemy' (maybe misspelled?)
Scanning index of all packages (this may take a while)
Reading http://www.python.org/pypi/
Reading http://www.python.org/pypi/SQLAlchemy/0.3.5
Reading http://www.sqlalchemy.org
Best match: SQLAlchemy 0.3.5
Downloading http://cheeseshop.python.org/packages/source/S/SQLAlchemy/SQLAlchemy-0.3.5.tar.gz#md5=5d4a317c542247f82d1ed7e256976117
Processing SQLAlchemy-0.3.5.tar.gz
Running SQLAlchemy-0.3.5/setup.py -q bdist_egg --dist-dir /tmp/easy_install-V_VxP8/SQLAlchemy-0.3.5/egg-dist-tmp-aRiBOE
zip_safe flag not set; analyzing archive contents...
Adding SQLAlchemy 0.3.5 to easy-install.pth file

Installed /usr/lib/python2.4/site-packages/SQLAlchemy-0.3.5-py2.4.egg
Processing dependencies for sqlalchemy

詳細

エラーは、/usr/lib/python2.4/site-package/TurboGears-1.0.1-py2.4-egg/turbogears/paginate.pyの以下の箇所で発生しています。

def sql_order_col(col, ascending=True):
    """Return an ordered col for col."""
    if isinstance(col, sqlalchemy.schema.Column):
        if ascending:
            order_col = sqlalchemy.sql.asc(col)
        else:
            order_col = sqlalchemy.sql.desc(col)
    elif isinstance(col, types.InstanceType):
        # I don't like using InstanceType, but that's what sqlobject col type
        # is.
        if ascending:
            order_col = col
        else:
            order_col = sqlobject.DESC(col)
    else:
        raise StandardError, 'expected Column, but got %s' % str(type(col))
    return order_col

ここでsqlalchemyモジュールを参照していることが問題です。ファイルの冒頭で、SQLAlchemyがない場合の対処をしているのですが、

try:
    # Can't depend on sqlalchemy being available.
    import sqlalchemy
    from sqlalchemy.ext.selectresults import SelectResults as SASelectResults
except ImportError:
    SASelectResults = None

実際にはコードの中で使われてしまっているので、この対応方法は中途半端です。

よって、モデルにSQLObjectを使っていても、@paginateデコレータで並び順を指定する場合は、SQLAlchemyが必要です。

所感

んなアホな...。