2

質問するのは恥ずかしいですが、私は webapp2 を使用しており、この google webapp2 route function に基づいてルートを簡単に定義できるようにするソリューションをテンプレート化しています。しかし、それはすべてTYPE_NAME、子レベルで定義できるかどうかにかかっています。アイデアは、親がすべてを設定し、子は_list関数を実装するだけでよいというものです。私が遭遇した問題TYPE_NAMEは None であり、それを子にする必要があります。

#main WSGI is extended to have this function 
class WSGIApplication(webapp2.WSGIApplication):
    def route(self, *args, **kwargs):
        def wrapper(func):
            self.router.add(webapp2.Route(handler=func, *args, **kwargs))
            return func

        return wrapper

from main import application
class ParentHandler(RequestHandler):
    TYPE_NAME = None

    @application.route('/', name="list_%s" %TYPE_NAME)
    def list(self):
          return self._list()

class ChildHandler(ParentHandler):
    TYPE_NAME = 'child'

    def _list(self):
         return []

「クラスプロパティ」を使用していくつかのソリューションを試しましたが、うまくいきませんでした。他のアイデアも受け入れますが、基本的には、装飾されたプロパティを継承して実行する子クラスが必要なだけです。

編集:

これをどのように修正するのか疑問に思っている席の端にいるすべての人のために、デコレータから必要なものすべてを取り出すことができなかったので、メタを使用することになりました。_URLSまた、追加の「ルート」を追加できるようにするパラメーターも追加しました。custom関数をルートにマップ します。本当にデコレータを使いたかったのですが、うまくいきませんでした。

class RequestURLMeta(type):
    def __new__(mcs, name, bases, dct):
        result = super(RequestURLMeta, mcs).__new__(mcs, name, bases, dct)
        urls = getattr(result, '_URLS', {}) or {}
        for k,v in urls.iteritems():
            template = v.pop('template')
            app.route(getattr(result, k), template, **v)

        if getattr(result, 'TYPE_NAME', None):
            app.route(result.list, result.ROOT_PATH, methods=['GET'],name="%s" % result.TYPE_NAME)
        #other ones went here..

    return result

class ParentHandler(RequestHandler):
    __metaclass__ = RequestURLMeta


class ChildHandler(ParentHandler):
    TYPE_NAME = 'child'
    _URLS = { 'custom': '/custom', 'TYPE_NAME': 'custom_test' }
    def _list(self):
        return []
    def custom(self):  pass
4

2 に答える 2

1

これを機能させるには、メタクラスを使用する必要があると思います。次のようになります(テストされていません)。

from main import application

class RouteMeta(type):
    def __new__(mcs, name, bases, dct):
        type_name = dct.get("TYPE_NAME")
        if type_name is not None:
            @application.route('/', type_name)
            def list(self):
                return self._list()
            dct["list"] = list
        return super(RouteMeta, mcs).__new__(mcs, name, bases, dct)

class ParentHandler(RequestHandler):
    __metaclass__ = RouteMeta

class ChildHandler(ParentHandler):
    TYPE_NAME = 'child'

    def _list(self):
         return []

list()メソッドに属性を持たせる代わりに、ParentHandler継承しParentHandlerTYPE_NAME定義したクラスに対して動的に作成されます。

RequestHandlerカスタムメタクラスも使用する場合は、の代わりにRouteMetaから継承します。RequestHandler.__metaclass__type

于 2013-01-25T18:29:19.503 に答える
0

このコード:

@application.route('/', name="list_%s" %TYPE_NAME)
def list(self):*emphasized text*
    ...

意味的にはこれと同じです:

def list(self):
    ...
list = application.route('/', name="list_%s" %TYPE_NAME)(list)

つまり、メソッドrouteParentHandlerスコープ内で呼び出され、どんな遅延メソッドを試しても機能しません。別のことを試してください:

from main import application

def route_list(klass):
    klass.list = application.route('/',
        name="list_%s" % klass.TYPE_NAME)(klass.list)
    return klass

class ParentHandler(RequestHandler):

    def list(self):
          return self._list()

class ChildHandler(ParentHandler):
    TYPE_NAME = 'child'

    def _list(self):
         return []

# in python3 would be:
# @route_list
# class ChildHandler(ParentHandler):
#   ...
ChildHandler = route_list(ChildHandler)
于 2013-01-25T18:22:01.383 に答える