这似乎会出现很多问题,但我找不到任何文档。
我正在写一个api,我希望网址看起来像这样:
'/api/v1.0/restaurant/Name&Address'
使用Flask-restful,我已将网址定义为
'/api/v1.0/restaurant/<name>&<address>'
然而Werkzeug并不喜欢这样,并在werkzeug / routing.py中引发了一个BuildError
当我使用add_resource定义url时,为
'/api/v1.0/restaurant/<name>'
并硬连接地址,一切正常。
如何定义带两个变量的网址?
修改
Traceback (most recent call last):
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 397, in wrapper
resp = resource(*args, **kwargs)
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask/views.py", line 84, in view
return self.dispatch_request(*args, **kwargs)
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 487, in dispatch_request
resp = meth(*args, **kwargs)
File "/home/ubuntu/Hotsauce/api/app/views.py", line 75, in get
resto = {'restaurant': marshal(restaurant, resto_fields)}
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 533, in marshal
return OrderedDict(items)
File "/usr/lib/python2.7/collections.py", line 52, in __init__
self.__update(*args, **kwds)
File "/home/ubuntu/.virtualenvs/data/lib/python2.7/_abcoll.py", line 547, in update
for key, value in other:
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 532, in <genexpr>
for k, v in fields.items())
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask_restful/fields.py", line 232, in output
o = urlparse(url_for(self.endpoint, _external = self.absolute, **data))
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask/helpers.py", line 312, in url_for
return appctx.app.handle_url_build_error(error, endpoint, values)
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask/app.py", line 1641, in handle_url_build_error
reraise(exc_type, exc_value, tb)
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/flask/helpers.py", line 305, in url_for
force_external=external)
File "/home/ubuntu/.virtualenvs/data/local/lib/python2.7/site-packages/werkzeug/routing.py", line 1620, in build
raise BuildError(endpoint, values, method)
BuildError: ('restaurant', {u'city_id': 2468, u’score’: Decimal('0E-10'), 'id': 37247, u'nbhd_id': 6596, u'address_region': u'NY', u'phone_number': u'(718) 858-6700', '_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x26f33d0>, u'complete': False, u'name': u'Asya', u'address_locality': u'New York', u'address_updated': True, u'street_address': u'46 Henry St'}, None)
以下是生成错误的相关代码:
resto_fields = {
'id': fields.Integer,
'name': fields.String,
'street_address': fields.String,
'address_locality': fields.String,
'address_region': fields.String,
‘score’: fields.Float,
'phone_number': fields.String,
'uri': fields.Url('restaurant')
}
def get(self, name, address):
restaurant = session.query(Restaurant).filter_by(name=name).filter_by(address=address)
resto = {'restaurant': marshal(restaurant, resto_fields)}
return resto
答案 0 :(得分:2)
这与&
&符号无关,也与使用多个URL参数无关。
您只能使用端点中resto_fields
输出字段映射中的条目;你的address
映射中没有 resto_fields
条目,但你的restaurant
端点要求它构建网址。
在输出字段中添加address
字段,或使用路线中的一个现有字段。
答案 1 :(得分:1)
这不太理想,但它让事情有效。
在使用resto_fields进行编组期间,当burn-restful试图为资源创建uri时,问题就出现了。
当url仅将name作为变量时,这不是问题,但是,一旦url需要名称和地址,就会引发BuildError。
为解决此问题,我删除了
'uri': fields.Url('restaurant')
来自restos_fields的,在编组资源后构造了uri,并在返回之前将其添加到编组资源中。
resto = {'restaurant': marshal(restaurant, resto_fields)}
resto['restaurant']['uri'] = '/api/v1.0/restaurant/{0}&{1}'.format(name, address)
return resto
如果有人有更优雅的方式来完成这项工作,我很想听到它。
答案 2 :(得分:0)
我花了一段时间来弄清楚这一点,所以纠正的答案......
对于这种情况,@ Martijn的回答并不完全正确。正确的是:您必须拥有数据字典中<{1}}方法所需的属性(输出字段中的不)。
所以你的代码应该像这样工作:
get
resto_fields = {
'id': fields.Integer,
'name': fields.String,
'street_address': fields.String,
'address_locality': fields.String,
'address_region': fields.String,
‘score’: fields.Float,
'phone_number': fields.String,
'uri': fields.Url('restaurant')
}
def get(self, name, address):
restaurant = session.query(Restaurant).filter_by(name=name).filter_by(address=address)
# restaurant must have an 'address' field
restaurant['address'] = ' '.join[restaurant['street_address'], restaurant['address_locality']]
resto = {'restaurant': marshal(restaurant, resto_fields)}
return resto
将不成为生成的响应的一部分