在RESTapi

时间:2017-02-15 18:27:45

标签: python json rest flask flask-restful

我在使用RESTful API中的POST命令将json数据保存到我的postgres数据库时遇到问题。数据被接受,但键值彼此互换。我已经附加了PUT命令以及生成的数据库。我的代码中出现了什么错误导致了这样一个奇怪的问题?

以下是用于管理我们网页的python文件(省略了空间的不必要部分) 的初始化的.py

from flask import Flask, render_template, flash, request, url_for, redirect,session
from models import db, Users
from forms import SignupForm
from secrets import whole_string
import config
import logging
from logging.handlers import RotatingFileHandler
from flask_bcrypt import Bcrypt
from flask_restful import Resource, Api
from views import table_master

app = Flask(__name__)

db.init_app(app)
api = Api(app)
api.add_resource(table_master, '/api/master_animal/<cownumber>')
api.add_resource(table_master, '/api/master_animal/', endpoint = "cownumber")

if __name__ == '__main__':
    handler = RotatingFileHandler('barnyard.log', maxBytes=10000, backupCount=1)
    handler.setLevel(logging.INFO)
    app.logger.addHandler(handler)
    #app.run(debug = True)

视图的.py

from flask import Blueprint, request, jsonify, make_response
from models import UsersSchema, db, Master_animal, Master_animal_Schema
from flask_restful import Api, Resource
from sqlalchemy.exc import SQLAlchemyError
from marshmallow import ValidationError
import sys

master_animal= Blueprint('master_animal', __name__) # Seems to only change the format of returned json data
schemaMaster = Master_animal_Schema()

# master_animal table
class table_master(Resource):

    def get(self, cownumber):
        master_animal_query = Master_animal.query.get_or_404(cownumber)
        #Serialize the query results in the JSON API format
        result = schemaMaster.dump(master_animal_query).data
        return result

    def post(self):
        raw_dict = request.get_json(force=True)
        master_dict = raw_dict['data']['attributes']
        print >> sys.stderr, "data {}".format(raw_dict)
        try:
                #Validate the data or raise a Validation error if
                schemaMaster.validate(master_dict)
                #Create a master object with the API data recieved
                master = Master_animal(master_dict['cownumber'], master_dict['weight'], master_dict['height'])
                master.add(master)
                query = Master_animal.query.all()
                results = schemaMaster.dump(query, many = True).data
                return results, 201


        except ValidationError as err:
                resp = jsonify({"error": err.messages})
                resp.status_code = 403
                return resp               

        except SQLAlchemyError as e:
                db.session.rollback()
                resp = jsonify({"error": str(e)})
                resp.status_code = 403
                return resp

模型的.py

import sys

from flask import Flask
from flask_bcrypt import Bcrypt
from secrets import whole_string
from marshmallow_jsonapi import Schema, fields
from marshmallow import validate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.exc import SQLAlchemyError


app = Flask(__name__)
bcrypt = Bcrypt(app)
app.config['SQLALCHEMY_DATABASE_URI'] = whole_string
db = SQLAlchemy()


#Class to add, update and delete data via SQLALchemy sessions
class CRUD():   

    def add(self, resource):
        db.session.add(resource)
        return db.session.commit()   

    def update(self):
        return db.session.commit()

    def delete(self, resource):
        db.session.delete(resource)
        return db.session.commit()

class Master_animal(db.Model, CRUD):
    __tablename__ = 'master_animal'
    cownumber = db.Column(db.Text, primary_key = True)
    height = db.Column(db.Float)
    weight = db.Column(db.Float)

    def __init__(self, cownumber, height, weight):
        self.cownumber = cownumber
        self.height = height
        self.weight = weight

class Master_animal_Schema(Schema):
    not_blank = validate.Length(min=1, error ='Field cannot be blank')
    id = fields.Integer(dump_only=True) #WHY DOES THIS HAVE TO BE HERE???
    cownumber = fields.String(validate = not_blank)
    height = fields.Float(validate = not_blank)
    weight = fields.Float(validate = not_blank)

    # self links
    def get_top_level_links(self, data, many):
        print >> sys.stderr, "data {}".format(data) # print data to verify get request
        if many:
            self_link = "/master_animal/"
        else:
            self_link = "/master_animal/{}".format(data['attributes']['cownumber'])
        return {"self":self_link}
    class Meta:
        type_ = 'master_animal' 

在邮递员中使用PUT

example.com/api/master_animal /

体:

{
  "data": {
    "attributes": {
      "cownumber": "1344",
      "height": 56,
      "weight": 230
    }}}

在我们的postgreSQL数据库中,高度和重量的值互换

barnyard=# Select * from master_animal;
 cownumber | height | weight
-----------+--------+--------
 1235      |    189 |     32
 1253      |    156 |     23
 1254      |    183 |     54
 1344      |    230 |     56

每个PUT命令都会生成此格式。

我不知道为什么会这样做或如何解决问题

1 个答案:

答案 0 :(得分:1)

我怀疑问题是你实例化Master_animal对象的地方。你几乎肯定会在那里使用关键字参数。

master = Master_animal(cownumer=master_dict['cownumber'], weight=master_dict['weight'], height=master_dict['height'])