【发布时间】:2014-01-02 20:33:12
【问题描述】:
我目前正在使用 EndpointsModel 为我在 AppEngine 上的所有模型创建一个 RESTful API。由于是 RESTful,这些 api 有很多我想避免的重复代码。
例如:
class Reducer(EndpointsModel):
name = ndb.StringProperty(indexed=False)
@endpoints.api(
name="bigdata",
version="v1",
description="""The BigData API""",
allowed_client_ids=ALLOWED_CLIENT_IDS,
)
class BigDataApi(remote.Service):
@Reducer.method(
path="reducer",
http_method="POST",
name="reducer.insert",
user_required=True,
)
def ReducerInsert(self, obj):
pass
## and GET, POST, PUT, DELETE
## REPEATED for each model
我想让它们变得通用。所以我尝试向类动态添加方法。 到目前为止我尝试过的:
from functools import partial, wraps
def GenericInsert(self, obj, cls):
obj.owner = endpoints.get_current_user()
obj.put()
return obj
# Ignore GenericDelete, GenericGet, GenericUpdate ...
import types
from functools import partial
def register_rest_api(api_server, endpoint_cls):
name = endpoint_cls.__name__
# create list method
query_method = types.MethodType(
endpoint_cls.query_method(
query_fields=('limit', 'pageToken'),
path="%ss" % name,
http_method="GET",
name="%s.list" % name,
user_required=True
)(partial(GenericList, cls=endpoint_cls)))
setattr(api_server, "%sList", query_method)
# create insert method
# ...
register_rest_api(BigDataApi, Reducer)
但我得到了'functools.partial' object has no attribute '__module__' exception.
我认为是因为endpoints.method的装饰器和部分装饰器之间存在一些冲突。但不知道如何避免它。
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 239, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 298, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 84, in LoadObject
obj = __import__(path[0])
File "/Users/Sylvia/gcdc2013/apis.py", line 795, in <module>
register_rest_api(BigDataApi, Reducer)
File "/Users/Sylvia/gcdc2013/apis.py", line 788, in register_rest_api
)(partial(GenericList, cls=endpoint_cls)))
File "/Users/Sylvia/gcdc2013/endpoints_proto_datastore/ndb/model.py", line 1544, in RequestToQueryDecorator
@functools.wraps(api_method)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/functools.py", line 33, in update_wrapper
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'functools.partial' object has no attribute '__module__'
相关文章:
【问题讨论】:
-
这个问题可能会更短,例如,只需解释
GenericInsert的问题。 -
不仔细看,似乎如果您有命名冲突,那么
from functools import partial->import functools甚至from functools import partial as part或其他可能会起作用。 -
问题的本质是 functools.wraps (被端点代码使用,但不是以任何方式错误或不寻常的方式)期望被包装的可调用对象具有 __module__ 属性(除其他外)。您传递的方法没有。 bugs.python.org/issue3445 表明这被认为对于 python 3.3 是值得修复的,但对于 2.7 则不是。所以你可能只需要以不同的方式做事......没有太多的答案,抱歉。
-
@Greg 谢谢,该链接对解释问题非常有用
-
@Greg。您还建议通过哪些其他方式来修复一个函数的参数?
标签: python google-app-engine google-cloud-endpoints functools endpoints-proto-datastore