'Flask Server API using classes starts causing problems with nested URIs (werkzeug.routing.BuildError)
Today I bring you a new question due to my inexperience, eagerness to learn and desire for my project to work.
I have created a Flask server that will serve as my API (I know it's a horrible decision from what I've read, but let me learn strange moves).
from flask import Flask
from flask_cors import CORS
from flask_restful import Api
app = Flask(__name__)
api = Api(app)
CORS(app)
from classes.CommentAPI import CommentAPI
api.add_resource(CommentAPI, '/comments/<int:id>', endpoint='comment')
from classes.CommentListAPI import CommentListAPI
api.add_resource(CommentListAPI, '/comments', endpoint='comments')
from classes.FollowerAPI import FollowerAPI
api.add_resource(FollowerAPI, '/followers/<int:id>', endpoint='follower')
[...]
from classes.Groups.GroupAPI import GroupAPI
api.add_resource(GroupAPI, '/groups/<int:id>', endpoint='group')
from classes.Groups.GroupListAPI import GroupListAPI
api.add_resource(GroupListAPI, '/groups', endpoint='groups')
from classes.Groups.GroupCommentAPI import GroupCommentAPI
api.add_resource(GroupCommentAPI, '/groups/<int:group_id>/comments/<int:id>', endpoint='group_comment')
from classes.Groups.GroupCommentListAPI import GroupCommentListAPI
api.add_resource(GroupCommentListAPI, '/groups/<int:id>/comments', endpoint='group_comments')
from classes.Groups.GroupLikeAPI import GroupLikeAPI
api.add_resource(GroupLikeAPI, '/groups/<int:group_id>/likes/<int:id>', endpoint='group_like')
from classes.Groups.GroupLikeListAPI import GroupLikeListAPI
api.add_resource(GroupLikeListAPI, '/groups/<int:id>/likes', endpoint='group_likes')
from classes.Groups.GroupMemberAPI import GroupMemberAPI
api.add_resource(GroupMemberAPI, '/groups/<int:group_id>/members/<int:id>', endpoint='group_member')
[...]
All API calls to non-group URIs work fine. The problem with the group functions is that it seems that the logic of the classes that I have created is not working well.
The error that pops up when I make a call like this:
http://<SERVER>/groups/1/comments/1
It is the following:
[2022-05-03 22:47:23,007] ERROR in app: Exception on /groups/1/comments/1 [GET]
Traceback (most recent call last):
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask/app.py", line 1523, in full_dispatch_request
rv = self.dispatch_request()
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask/app.py", line 1509, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask_restful/__init__.py", line 467, in wrapper
resp = resource(*args, **kwargs)
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask/views.py", line 84, in view
return current_app.ensure_sync(self.dispatch_request)(*args, **kwargs)
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask_restful/__init__.py", line 582, in dispatch_request
resp = meth(*args, **kwargs)
File "/home/lorty/Escritorio/proyectos/espaCy_API/classes/Groups/GroupCommentAPI.py", line 18, in get
return {'group_comment': marshal(group_comment[0], group_comment_fields)}
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask_restful/__init__.py", line 635, in marshal
return OrderedDict([(envelope, OrderedDict(items))]) if envelope else OrderedDict(items)
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask_restful/__init__.py", line 633, in <genexpr>
else make(v).output(k, data))
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask_restful/fields.py", line 304, in output
o = urlparse(url_for(endpoint, _external=self.absolute, **data))
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask/helpers.py", line 336, in url_for
return appctx.app.handle_url_build_error(error, endpoint, values)
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/flask/helpers.py", line 323, in url_for
rv = url_adapter.build(
File "/home/lorty/Escritorio/proyectos/espaCy_API/venv/lib/python3.9/site-packages/werkzeug/routing.py", line 2305, in build
raise BuildError(endpoint, values, method, self) werkzeug.routing.BuildError: Could not build url for endpoint 'group_comment' with values ['author', 'content', 'group_post_id', 'id']. Did you forget to specify values ['group_id']?
127.0.0.1 - - [03/May/2022 22:47:23] "GET /groups/1/comments/1 HTTP/1.1" 500 -
Here are the 'group_likes' and 'group_comments' classes as examples:
GroupCommentAPI.py
from flask_restful import Resource, reqparse, abort, marshal
from classes.data_classes.groups.group_comments import group_comments, group_comment_fields
class GroupCommentAPI(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument('content', type=str, location='json')
self.reqparse.add_argument('author', type=str, location='json')
self.reqparse.add_argument('group_post_id', type=int, location='json')
super(GroupCommentAPI, self).__init__()
def get(self, group_id, id):
group_comment = [group_comment for group_comment in group_comments if group_comment['id'] == id and group_comment['group_post_id'] == group_id]
if len(group_comment) == 0:
abort(404)
return {'group_comment': marshal(group_comment[0], group_comment_fields)}
def put(self, group_id, id):
group_comment = [group_comment for group_comment in group_comments if group_comment['id'] == id and group_comment['group_post_id'] == group_id]
if len(group_comment) == 0:
abort(404)
group_comment = group_comment[0]
args = self.reqparse.parse_args()
for k, v in args.items():
if v is not None:
group_comment[k] = v
return {'group_comment': marshal(group_comment, group_comment_fields)}
def delete(self, group_id, id):
group_comment = [group_comment for group_comment in group_comments if group_comment['id'] == id and group_comment['group_post_id'] == group_id]
if len(group_comment) == 0:
abort(404)
group_comments.remove(group_comment[0])
return {'result': True}
GroupCommentListAPI.py
from flask_restful import Resource, reqparse, marshal
from classes.data_classes.groups.group_comments import group_comment_fields, group_comments
class GroupCommentListAPI(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument('content', type=str, required=True, help='No group comment content provided', location='json')
self.reqparse.add_argument('author', type=str, required=True, help='No group comment author provided', location='json')
self.reqparse.add_argument('group_post_id', type=int, required=True, help='No group post ID provided', location='json')
super(GroupCommentListAPI, self).__init__()
def get(self, id):
return {'group_comments': [marshal(group_comment, group_comment_fields) for group_comment in group_comments if group_comment['group_post_id'] == id]}
def post(self):
args = self.reqparse.parse_args()
group_comment = {
'id': group_comments[-1]['id'] + 1 if len(group_comments) > 0 else 1,
'content': args['content'],
'author': args['author'],
'group_post_id': args['group_post_id']
}
group_comments.append(group_comment)
return {'group_comment': marshal(group_comment, group_comment_fields)}, 201
GroupLikeAPI.py
from flask_restful import Resource, reqparse, marshal, abort
from classes.data_classes.groups.group_likes import group_likes, group_like_fields
class GroupLikeAPI(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument('author', type=str, location='json')
self.reqparse.add_argument('group_post_id', type=int, location='json')
super(GroupLikeAPI, self).__init__()
def get(self, group_id, id):
group_like = [group_like for group_like in group_likes if group_like['id'] == id and group_like['group_post_id'] == group_id]
if len(group_like) == 0:
abort(404)
return {'group_like': marshal(group_like[0], group_like_fields)}
def put(self, group_id, id):
group_like = [group_like for group_like in group_likes if group_like['id'] == id and group_like['group_post_id'] == group_id]
if len(group_like) == 0:
abort(404)
group_like = group_like[0]
args = self.reqparse.parse_args()
for k, v in args.items():
if v != None:
group_like[k] = v
return {'group_like': marshal(group_like, group_like_fields)}
def delete(self, group_id, id):
group_like = [group_like for group_like in group_likes if group_like['id'] == id and group_like['group_post_id'] == group_id]
if len(group_like) == 0:
abort(404)
group_likes.remove(group_like[0])
return {'result': True}
GroupLikeListAPI.py
from flask_restful import Resource, reqparse, marshal
from classes.data_classes.groups.group_likes import group_like_fields, group_likes
class GroupLikeListAPI(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument('author', type=str, required=True, help='No group like author provided', location='json')
self.reqparse.add_argument('group_post_id', type=int, required=True, help='No group post ID provided', location='json')
super(GroupLikeListAPI, self).__init__()
def get(self, id):
return {'group_likes': [marshal(group_like, group_like_fields) for group_like in group_likes if group_like['group_post_id'] == id]}
def post(self):
args = self.reqparse.parse_args()
group_like = {
'id': group_likes[-1]['id'] + 1 if len(group_likes) > 0 else 1,
'author': args['author'],
'group_post_id': args['group_post_id']
}
group_likes.append(group_like)
return {'group_like': marshal(group_like, group_like_fields)}, 201
What is going wrong? What is causing the error? How could I fix it?
A greeting and thanks in advance.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
