14.3 资源和JSON之间的转换

    JSON是http请求和响应使用的传输格式, 那么Web服务就应该实现以下两个功能:

  1.         把资源转换成json数据——发送给客户端
  2.         把json数据转换成资源——把客户端发送过来的json数据转换成资源存储在数据库中

一. 把资源转换成json数据

1) app/models.py

class Post(db.Model):

    #...

    def to_json(self):

        json_post = {

            'url': url_for('api.get_post', id = self.id, _external=True),

            'body': self.body,

            'body_html': self.body_html,

            'timestamp': self.timestamp,

            'author': url_for('api.get_user', id=self.author_id, _external=True),

            'comments': url_for('api.get_post_comments', self.id, _external=True),

            'comment_count': self.comments.count()

        }

        return json_post

    #_external参数是为了生成完整的url, 在客户端只能使用完整的url

    #上面的代码还说明了生成json数据时可以使用虚构的属性(ps:comment_count)


class User(db.Model):

    #...

    def to_json(self):

        json_user = {

            'url': url_for('api.get_user', id=self.id, _external=True),

            'username': self.username,

            'member_since': self.member_since,

            'last_seen': self.last_seen,

            'posts': url_for('api.get_user_posts', self.id, _external=True),

            'followed_posts': url_for('api.get_user_followed_posts', self.id, _external=True),

            'post_count': self.posts.count()

        }

        return json_user

#为了保护隐私, 用户的某些属性没有加入响应, 比如email和role等

#这说明提供给客户端的资源没有必要和数据库模型内部完全一致

二. 把json转换成资源

1)app/models.py

from app.exceptions import ValidationError

class Post(db.Model):

    #...

    @staticmethod

    def from_json(json_post):

        body = json_post.get('body')

        if body is None or body == '':

            raise ValidationError('post dose not have a body')

    return Post(body=body)

#我们创建Post实例时只用了json中的body字段
#不需要body_html字段, because我们之前为数据库的Post表的body字段设置了事件监听, 一旦实例的body属性被修改就会自动修改body_html
#不需要timestamp字段, because timestamp有默认值, 即创建时间
#不需要author, because author的值不是客户端确定的, author的值是通过认证的用户
#不需要url, because url的值也不是客户端确定的, 是数据库分配id后决定的

当body值不存在的时候, 引发ValidationError, 由调用函数的上层函数处理这个错误。

为了不再视图函数中捕获该错误, 我们在api蓝本全局中处理该错误:

2) app/api__1_0/errors.py

@api.errorhandler(ValidationError)

der validation_error(e):

    return bad_request(e.args[0])

#只要在api注册的路由中遇到ValidationError的错误, 就会由该函数处理返回响应。

这样的话视图函数就会简洁一些:

3)app/api_1_0/posts.py


@api.route('/posts', method=['POST'])

def new_post():

    post = Post.from_json(request.json)

    post.author = g.current_user

    db.session.add(post)

    db.session.commit()

     return jsonify(post.to_json())
#当用户编辑完文章点击提交按钮时, 客户端对文章内容进行json编码, 并把内容提交到响应url
#由于该url是api注册的, 要先进行认证, 认证通过后, g.current_user存储当前用户
#执行该视图函数, 先从请求对象中获取json_post, 转换成资源post
#post.author就是g.current_user


   





   





   

   


猜你喜欢

转载自blog.csdn.net/sinat_34927324/article/details/80612639