官术网_书友最值得收藏!

Handling resources

A typical RESTful application has the following general structure:

  1. A URL-defined resource. This resource allows one or more actions through HTTP methods (GET, POST, and so on).
  2. When each of the actions is called, the framework routes the request until the defined code executes the action.
  3. If there are any input parameters, they'll need to be validated first.
  4. Perform the action and obtain a result value. This action will normally involve one or more calls to the database, which will be done in the shape of models.
  5. Prepare the resulting result value and encode it in a way that's understood by the client, typically in JSON.
  6. Return the encoded value to the client with the adequate status code.

Most of these actions are done by the framework. Some configuration work needs to be done, but it's where our web framework, Flask-RESTPlus in this example, will help the most. In particular, everything but step 4 will be greatly simplified.

Let's take a look at a simple code example (available in GitHub) to describe it:

api_namespace = Namespace('api', description='API operations')

@api_namespace.route('/thoughts/<int:thought_id>/')
class ThoughtsRetrieve(Resource):

@api_namespace.doc('retrieve_thought')
@api_namespace.marshal_with(thought_model)
def get(self, thought_id):
'''
Retrieve a thought
'''
thought = ThoughtModel.query.get(thought_id)
if not thought:
# The thought is not present
return '', http.client.NOT_FOUND

return thought

This implements the GET /api/thoughts/X/ action, retrieving a single thought by ID.

Let's analyze each of the elements. Note the lines are grouped thematically:

  1. First, we define the resource by its URL. Note that api_namespace sets the api prefix to the URL, which validates that parameter X is an integer:
api_namespace = Namespace('api', description='API operations')

@api_namespace.route('/thoughts/<int:thought_id>/')
class ThoughtsRetrieve(Resource):
...
  1. The class allows you to perform multiple actions on the same resource. In this case, we only do one: the GET action.
  2. Note that the thought_id parameter, encoded in the URL, is passed as a parameter to the method:
class ThoughtsRetrieve(Resource):

def get(self, thought_id):
...
  1. We can now execute the action, which is a search in the database to retrieve a single object. Call ThoughModel to search for the specified thought. If found, it's returned with a http.client.OK (200) status code. If it's not found, an empty result and a http.client.NOT_FOUND 404 status code is returned:
def get(self, thought_id):
thought = ThoughtModel.query.get(thought_id)
if not thought:
# The thought is not present
return '', http.client.NOT_FOUND

return thought
  1. The thought object is being returned. The marshal_with decorator describes how the Python object should be serialized into a JSON structure. We'll see later how to configure it:
@api_namespace.marshal_with(thought_model)
def get(self, thought_id):
...
return thought
  1. Finally, we have some documentation, including the docstring that will be rendered by the autogenerated Swagger API:
class ThoughtsRetrieve(Resource):

@api_namespace.doc('retrieve_thought')
def get(self, thought_id):
'''
Retrieve a thought
'''
...

As you can see, most of the actions are configured and performed through Flask-RESTPlus, and the bulk of the work as a developer is the meaty step 4. There's work to do, though, configuring what the expected input parameters are and validating them, as well as how to serialize the returning object into proper JSON. We'll see how Flask-RESTPlus can help us with that.

主站蜘蛛池模板: 灵川县| 子洲县| 敦煌市| 涟水县| 陵川县| 尖扎县| 清苑县| 宜章县| 长子县| 黔江区| 博罗县| 沙洋县| 奎屯市| 曲麻莱县| 泰顺县| 东至县| 扬中市| 陕西省| 巴彦淖尔市| 巩义市| 岑巩县| 普陀区| 武定县| 九龙坡区| 兴仁县| 富宁县| 彭州市| 山东| 晋宁县| 任丘市| 淮北市| 方山县| 台山市| 定远县| 筠连县| 搜索| 弋阳县| 郸城县| 东乌珠穆沁旗| 皋兰县| 张家港市|