0

这似乎会出现很多,但我找不到任何文档。

我正在编写一个 api,我希望 url 看起来像这样:

'/api/v1.0/restaurant/Name&Address'

使用 Flask-restful,我将 url 定义为

'/api/v1.0/restaurant/<name>&<address>'

但是 Werkzeug 不喜欢这样,并在 werkzeug/routing.py 中引发了 BuildError

当我使用 add_resource 定义 url 时,

'/api/v1.0/restaurant/<name>'

并硬连线地址,一切正常。

如何定义 url 以获取两个变量?

编辑

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
4

3 回答 3

2

This has nothing to do with the & ampersand nor with with using more than one URL parameter.

You can only use entries from the resto_fields output fields mapping in your endpoint; you don't have an address entry in your resto_fields mapping, but your restaurant endpoint requires it to build the URL.

Add an address field to your output fields, or use one of the existing fields in the route.

于 2014-03-24T21:55:18.747 回答
1

这并不理想,但它可以让事情正常进行。

当 flask-restful 在使用 resto_fields 编组期间尝试为资源创建 uri 时,就会出现问题。

当 url 仅将 name 作为变量时,这不是问题,但是,一旦 url 需要 name&address,就会引发 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

如果有人有更优雅的方式来完成这项工作,我很想听听。

于 2014-03-24T21:23:13.163 回答
0

我花了一段时间才弄清楚这一点,所以一个更正的答案......

@Martijn 的回答对于这种情况并不完全正确。

正确的是:您必须在数据字典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

address不会是生成的响应的一部分

于 2015-04-28T05:49:20.780 回答