New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple GETs in same resource support/example? #114
Comments
You can't have two different GET endpoints on one resource class. To support GETs on those two routes, you'll need to break them into two different resources. It seems like you want to have a |
I see, Although I am not sure what the roadmap looks like for the project, but don't you think one resource should be able to support multiple |
I don't. Flask-RESTful is designed to make it very easy for users to design RESTful APIs. REST APIs have just one URL for a given resource. In a RESTful API, the two URLs in the example you provided above would be two separate resources and therefore would map to two separate classes each with their own implementation of the Basically, Flask-RESTful won't support multiple |
I think I understand you now, Thank you @dougblack |
What about the I have hacked around this by doing class User(Resource):
def get(self, id=None):
if id is None:
return users
else:
return user
def post(self):
#.... and then to register the resource api.add_resource(User, '/users', methods=['GET', 'POST'])
api.add_resource(User, '/users/<id>', methods=['GET', 'PATCH', 'DELETE']) but this breaks with Flask 0.10 |
Generally, RESTful APIs have Here's how I'd do what you're trying to accomplish. class Users(Resource):
def get(self):
return users
def post(self):
#...
class User(Resource):
def get(self, id=None):
return find_user_by_id(id)
def post(self):
#...
api.add_resource(Users, '/users')
api.add_resource(User, '/users/<id>') This is a perfectly normal way to build your API. If you find yourself wanting support for multiple GET methods on a resource, chances are you're not being RESTful and should probably reevaluate your design. |
Just to follow up on @dtheodor's comment. Your way is fine if you're okay managing the optional parameter. The issue in flask 0.10 is having conflicting endpoint names registered. By default flask-restful uses the classname as the endpoint but you can overwrite it as follows:
Also note that you don't need to specify methods as they are taken care of by the method functions you write/don't write in your Resource class. |
Great points! Thanks @frankstratton. |
I understand the different behavior between Anyway, things work as they are now, but this is an interesting discussion on design, which can always turn philosophical unless someone presents a concrete problem with the current design, which I don't really have at the moment. |
I'd like to open this question up again. What should we do if there really are two names for the same resource? GET /object/ ...assuming <type>+<name> is a unique constraint (composite key). Here we can access the same resource using two different URIs. It seems quite natural to implement two gets on the same class because we're dealing with the same object in the server, the same representation of its state, the same behavior. |
Sure, let's take a look. Let's think about what those two routes might be for.
Based on your description it seems that
If all of the assumptions I've made are correct, this would solve your problem, and you'd still be able to only have one from flask import Flask, request
from flask.ext import restful
class ObjectResource(restful.Resource):
def get(self):
obj_type = request.args.get('type', "")
obj_name = request.args.get('name', "")
objects = db.filter(type=obj_type, name=obj_name)
app = Flask(__name__)
api = restful.Api(app)
api.add_resource(ObjectResource, '/object') Alternatively, if you really want to use the URL to capture those parameters, you could do something like this: from flask import Flask, request
from flask.ext import restful
class ObjectResource(restful.Resource):
def get(self, type, name):
objects = db.filter(type=obj_type, name=obj_name)
app = Flask(__name__)
api = restful.Api(app)
api.add_resource(
ObjectResource,
'/object',
'/object/<type>/<name>',
defaults={'type': '', 'name': ''}
) Let me know if this looks okay. |
Somehow the was dropped from my intended post. The two routes are actually: GET /object/ And both refer to a single object and not a list resource. is a unique key over all objects and + is a unique composite key over all objects. Therefore there are two ways to uniquely identify the same object--either by specifying an or by specifying both a and --and I would like to expose both ways through a RESTful URL since there are separate use cases for both. I suspect this is quite common because many relational-object mappers will use an object ID even though there may be other natural keys or composite keys that also uniquely identify an object. On Oct 14, 2013, at 10:42 PM, Doug Black <notifications@github.commailto:notifications@github.com> wrote: Sure, let's take a look. Let's think about what those two routes might be for. GET /object Based on your description it seems that object is actually a ListResource that returns multiple instances of some other object. It also sounds like the second route is used to filter the list by type and name. At Twilio, we accomplish this by using query parameters to define the filter. So instead of encoding the filter parameters type and name in the URL, you'd include them in the query parameters: GET /object?type=mytype&name=myname If all of the assumptions I've made are correct, this would solve your problem, and you'd still be able to only have one get method. It might look something like this: from flask import Flask, request class ObjectResource(restful.Resource): app = Flask(name) Alternatively, if you really want to use the URL to capture those parameters, you could do something like this: from flask import Flask, request class ObjectResource(restful.Resource): app = Flask(name) Let me know if this looks okay. — This message (including any attachments) contains confidential information intended for a specific individual and purpose, and is protected by law. If you are not the intended recipient, you should delete this message. Any disclosure, copying, or distribution of this message, or the taking of any action based on it, is strictly prohibited. Unless specifically indicated, this message is not an offer to sell or a solicitation of any investment products or other financial product or service, an official confirmation of any transaction, or an official statement of StoneCastle. There is no guarantee that e-mail transmissions are secure or error-free as such transmissions can be intercepted, corrupted, lost or destroyed, or can arrive late or incomplete or can contain viruses. The sender does not accept liability for any errors or omissions in the contents, or delay in receipt, of this e-mail message or its attachments which arise in the course of its transmission or receipt, and does not guarantee that the message contains no viruses. |
what would you suggest to get user by id and email which belongs to same resource |
To me it seems like the tail of Flask's add_url_rule implementation is wagging the dog of our definitions of RESTful design here. Granted the GET case is open to debate, since GET in the list case often needs query parameters or some sort of qualifier in the route to explain what's being gotten. But having worked with both Java and Ruby in the past, neither one of which follow this convention as far as I know, it really made sense to me to have PUT, POST, DELETE, and two flavors of GET in the same Resource. I've create a GIST for a proof of concept of the solution, https://gist.github.com/JohnLockwood/d9fa9393be269322df1a . Cheers. |
If you look at the JAX-RS v1.1 specification and implementation of it such as Apache Wink, you will notice that handling multiple GETs in a single resource class is allowed and makes complete sense. Lacking support for this pattern is a major inconvenience. |
I'm late to the party... However, it is totally double! I admit that it wasn't clear. As you see below, you have to define many routes for one resource and then set None the arguments which vary:
Good luck! Taken from https://github.com/sevaivanov/ring-api/. |
How can I create POST, GET, PUT on one resource in flask restful?? |
@vimox-shah look at my example and add your post, get & put methods into a class representing your resource by inheriting from a |
@neelay-shah,You solved the issue ? |
@rayest also that comment is almost 4 years old now |
What if I have PATCH request. And all wanting to do separate things. |
Is there any other extension for Flask that respects this method? |
Have you managed to find the extension, or workaround? |
If anyone's looking here for a solution, Flask can now do this out of the box with MethodView (which is recommended as a replacement to Flask-RESTful's Resource) . |
Hello @RobSpectre @cummack @devinrader @dougblack @frankstratton
I have a following situation where I have
User
Resource and it needs following endpointsQuestion
How can I have two
@GET
endpoints in same resource class?Thank you
The text was updated successfully, but these errors were encountered: