Search code examples
pythonflaskflask-restful

how to specify values for field.url in flask-restful with endpoint


how to custom field.url in flask-restful.

user_fields = {
    ...
    'test': fields.Url('userep', absolute=True)
    ....
}

api.add_resource(User, '/user', '/user/<int:userid>', endpoint='userep')

when i submit http://127.0.0.1:5000/user/1

the result is like this : "test": "http://127.0.0.1:5000/user",

and change user_fields like this:

user_fields = {
    'id': fields.Integer,
    'friends': fields.Url('/Users/{id}/Friends'),

when i submit http://127.0.0.1:5000/user/1 throw error like those:

werkzeug.routing.BuildError

BuildError: Could not build url for endpoint '/Users/{id}/Friends' with values ['_sa_instance_state', 'email', 'id', 'nickname', 'password', 'regist_date', 'status']. Did you mean 'version' instead?

any advise? thx

for further,if i change resource

api.add_resource(User, '/user/<int:userid>', endpoint='userep')

the error message throw

werkzeug.routing.BuildError

BuildError: Could not build url for endpoint 'userep' with values ['_sa_instance_state', 'email', 'id', 'nickname', 'password', 'regist_date', 'status']. Did you forget to specify values ['userid']?

in official document field.url

class Url(Raw):
"""
A string representation of a Url
:param endpoint: Endpoint name. If endpoint is ``None``,
    ``request.endpoint`` is used instead
:type endpoint: str
:param absolute: If ``True``, ensures that the generated urls will have the
    hostname included
:type absolute: bool
:param scheme: URL scheme specifier (e.g. ``http``, ``https``)
:type scheme: str
"""
def __init__(self, endpoint=None, absolute=False, scheme=None):
    super(Url, self).__init__()
    self.endpoint = endpoint
    self.absolute = absolute
    self.scheme = scheme

def output(self, key, obj):
    try:
        data = to_marshallable_type(obj)
        endpoint = self.endpoint if self.endpoint is not None else request.endpoint
        o = urlparse(url_for(endpoint, _external=self.absolute, **data))
        if self.absolute:
            scheme = self.scheme if self.scheme is not None else o.scheme
            return urlunparse((scheme, o.netloc, o.path, "", "", ""))
        return urlunparse(("", "", o.path, "", "", ""))
    except TypeError as te:
        raise MarshallingException(te)

flask_restful/fields.py


Solution

  • answer by myself: this is no way to resolve problem.

    according flask-restful project issue: api.url_for() fails with endpoints specified by a string and Flask jsonify a list of objects

    code like this:

    from flask import url_for
    
    class ProjectsView(object):
        def __init__(self, projectid):
            self.projectid = projectid
            ...
    
        def serialize(self):
            return {
                ...
                'tasks_url':url_for('.getListByProjectID', _external=True, projectid=self.projectid),
            }
    
    class Projects(Resource):
        def get(self, userid):
            project_obj_list = []
            ...
            v = ProjectsView(project.id)
            project_obj_list.append(v)
    
        return jsonify(result=[e.serialize() for e in project_obj_list])
    

    and the response like this:

    {
      "result": [
        {
          ... 
          "tasks_url":"http://127.0.0.1:5000/api/v1.0/1/GetListByProjectID"
        }
      ]
    }