2

私はレポートタイプのことを行うアプリケーションに取り組んでおり、多くの場合、JSON で指定されたフィルターを取得し、それを SQLAlchemy クエリに変換してから、結果をブラウザーに送り返す必要があります (たとえば、フィルターstart_date: 1234, end_date: 5678, widget_ids: [1, 2, 3]を変換する必要があります)。クエリに… WHERE start_date >= 1234 AND end_date <= 5678 AND widget_id in (1, 2, 3))。

この種の変換を自動的に行うツールはありますか (たとえば、Django の ORM: のようなサフィックスを使用しますstart_date__ge: 1234, end_date__le: 5678, widget_id__in: [1, 2, 3])?

明らかに、そのようなスキームにはセキュリティとパフォーマンスへの影響があります...しかし、自分で構築する前に、このようなものが存在するかどうかを知りたいです.

編集:私は自分のものを構築できることを認識していますが、既存のツール/ライブラリがあるかどうかは特に疑問に思っているので、車輪を再発明する必要はありません。

4

3 に答える 3

3

興味深いかもしれないいくつかの簡単なコードがあります(source):

def create_attr_filter(request, mapped_class):
    """Create an ``and_`` SQLAlchemy filter (a ClauseList object) based
    on the request params (``queryable``, ``eq``, ``ne``, ...).

    Arguments:

    request
        the request.

    mapped_class
        the SQLAlchemy mapped class.
    """

    mapping = {
        'eq'   : '__eq__',
        'ne'   : '__ne__',
        'lt'   : '__lt__',
        'lte'  : '__le__',
        'gt'   : '__gt__',
        'gte'  : '__ge__',
        'like' : 'like',
        'ilike': 'ilike'
    }
    filters = []
    if 'queryable' in request.params:
        queryable = request.params['queryable'].split(',')
        for k in request.params:
            if len(request.params[k]) <= 0 or '__' not in k:
                continue
            col, op = k.split("__")
            if col not in queryable or op not in mapping.keys():
                continue
            column = getattr(mapped_class, col)
            f = getattr(column, mapping[op])(request.params[k])
            filters.append(f)
    return and_(*filters) if len(filters) > 0 else None
于 2012-04-28T06:54:00.350 に答える
2

みたいなことを書きました。私はこれを Python プロキシと呼んでいます。JSON 経由で RPC to Python を実行する Javascript API を提供します。

これは私のオープン ソース プロジェクトの一部です。

関連するファイルは次のとおりです。

http://code.google.com/p/pycopia/source/browse/trunk/WWW/pycopia/WWW/json.py#135

Javascript 側:

http://code.google.com/p/pycopia/source/browse/trunk/WWW/media/js/proxy.js

使用法:

http://code.google.com/p/pycopia/source/browse/trunk/storage/pycopia/db/webservice.py

サンプル構成:

http://code.google.com/p/pycopia/source/browse/trunk/storage/etc/storage.conf.example

ただし、これは完全なフレームワークの一部であり、残念ながら十分に文書化されていません。最新の Linux プラットフォームといくつかのセットアップが必要です。

しかし、そこから何かアイデアを得ることができるかもしれません。

CLI スタイル (argv) 文字列からクエリを作成するその他のコードを次に示します。動的な演算子の選択を行います。

def _get_query(self, argv):
    mapper = models.class_mapper(self._obj)
    args, kwargs = _query_args(argv[1:], self._environ)
    q = _session.query(self._obj)
    if args:
        grps, left = divmod(len(args), 3)
        if grps:
            for name, op, val in _by_three(args[:grps*3]):
                col = getattr(self._obj, name)
                opm = {"=": col.__eq__, 
                        ">": col.__gt__, 
                        "<": col.__lt__, 
                        "match": col.match, 
                        "contains": col.contains, 
                        "in": col.in_, 
                        "like": col.like}.get(op)
                if opm:
                    if op == "like":
                        val = val.replace("*", "%")
                        val = val.replace(".", "_")
                        if "%" not in val:
                            val = "%" + val + "%"
                    if op == "in":
                        val = val.split(",")
                    q = q.filter(opm(val))
        for name in args[grps*3:]:
            if name.startswith("="):
                q = q.order_by(name[1:])
    if kwargs:
        for name, value in kwargs.items():
            col = getattr(self._obj, name)
            value = CLI.clieval(value)
            q = q.filter(col.__eq__(value))
    return q

それはあなたも始めるかもしれません。

于 2012-04-27T08:15:29.927 に答える
1

サンプルを見ると、JSON文字列には が実際には含まれていないoperatorsため、 の 1 つであるかどうかは明確ではありません==, >=, <=, IN, etc。文字JSON列は簡単にdict.

単純なケースでは、名前付きの dict を指定してfilter_byhave ==を使用できます。

query_dict = {'name': 'parent-2', 'description': 'test', }
query = query.filter_by(**query_dict)

getattr同様に、SQLAlchemyで回答されたものを使用してクエリを作成することもできます- dict からクエリ フィルタを動的に作成しますが、これにはまだoperator条件を知る必要があります。以下のコードでは、 のみlikeが使用されています。

q = session.query(myClass)
for attr, value in web_dict.items():
    q = q.filter(getattr(myClass, attr).like("%%%s%%" % value))

演算子を動的に指定する必要がある場合は、さらに次を使用できますgetattr

klass, attr, oper, value = MyClass, "startDate", "__ge__", 1234
q = q.filter(getattr(getattr(klass, attr), oper)(value))
于 2012-04-27T06:58:33.337 に答える