我要创建一个Flask API(对我来说这是新领域),我对返回数据的方式不满意。
它可以工作并连接到数据库并返回数据(是的),但这是词典列表(boo)。
我想重新格式化它,以便在调用它时看起来有所不同。
烧瓶模型:
from flask import Flask, jsonify
from flask_restful import Api, Resource, reqparse, abort, fields, marshal_with
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
api = Api(app)
app.config["SQLALCHEMY_DATABASE_URI"] = 'postgres://postgres:[password]@127.0.0.1:5432/usagestats'
db = SQLAlchemy(app)
class StatsModel(db.Model):
#added in from edit1
def __getitem__(self, key):
return self.__dict__[key]
__tablename__ = "smogon_usage_stats"
id_ = db.Column(db.Integer, primary_key=True)
rank = db.Column(db.Integer, nullable=False)
pokemon = db.Column(db.String(50), nullable=False)
usage_pct = db.Column(db.Float, nullable=False)
raw_usage = db.Column(db.Integer, nullable=False)
raw_pct = db.Column(db.Float, nullable=False)
real = db.Column(db.Integer, nullable=False)
real_pct = db.Column(db.Float, nullable=False)
dex = db.Column(db.Integer, nullable=False)
date = db.Column(db.String(10), nullable=False)
tier = db.Column(db.String(50), nullable=False)
def __repr__(self):
return f"Stats(id = {id_}, rank = {rank}, pokemon = {pokemon}, usage_pct = {usage_pct}, raw_usage = {raw_usage}, raw_pct = {raw_pct}, real = {real}, real_pct = {real_pct})"
resource_fields = {
'id_': fields.Integer,
'rank': fields.Integer,
'pokemon': fields.String,
'usage_pct': fields.Float,
'raw_usage': fields.Integer,
'raw_pct': fields.Float,
'real': fields.Integer,
'real_pct': fields.Float,
'dex': fields.Integer,
'date': fields.String,
'tier': fields.String
}
class Stats(Resource):
@marshal_with(resource_fields)
def get(self, date, tier):
result = StatsModel.query.filter_by(date=date, tier=tier + "-1500").all()
return result
api.add_resource(Stats, "/stats/<string:date>/<string:tier>-1500")
if __name__ == "__main__":
app.run(host='127.0.0.1', port=3000, debug=True)
在调用时返回以下内容:
[
{'id_': 669551, 'rank': 153, 'pokemon': 'snorunt', 'usage_pct': 0.07347, 'raw_usage': 104, 'raw_pct': 0.127, 'real': 96, 'real_pct': 0.148, 'dex': 361, 'date': '2020-04', 'tier': 'gen8lc-1500'},
{'id_': 669552, 'rank': 154, 'pokemon': 'milcery', 'usage_pct': 0.0672, 'raw_usage': 108, 'raw_pct': 0.131, 'real': 87, 'real_pct': 0.134, 'dex': 868, 'date': '2020-04', 'tier': 'gen8lc-1500'},
{'id_': 669553, 'rank': 156, 'pokemon': 'cosmog', 'usage_pct': 0.0199, 'raw_usage': 26, 'raw_pct': 0.032, 'real': 19, 'real_pct': 0.029, 'dex': 789, 'date': '2020-04', 'tier': 'gen8lc-1500'}
]
但是我希望它看起来像这样:
{
"data":
'snorunt': {
'id_': 669551, 'rank': 153, 'pokemon': 'snorunt', 'usage_pct': 0.07347, 'raw_usage': 104, 'raw_pct': 0.127, 'real': 96, 'real_pct': 0.148, 'dex': 361, 'date': '2020-04', 'tier': 'gen8lc-1500'},
'milcery': {
'id_': 669552, 'rank': 154, 'pokemon': 'milcery', 'usage_pct': 0.0672, 'raw_usage': 108, 'raw_pct': 0.131, 'real': 87, 'real_pct': 0.134, 'dex': 868, 'date': '2020-04', 'tier': 'gen8lc-1500'},
'cosmog': {
'id_': 669553, 'rank': 156, 'pokemon': 'cosmog', 'usage_pct': 0.0199, 'raw_usage': 26, 'raw_pct': 0.032, 'real': 19, 'real_pct': 0.029, 'dex': 789, 'date': '2020-04', 'tier': 'gen8lc-1500'
}
}
我尝试在result
类中操作Stats
,但是它引发了一个错误(我已经将其取出来了,但这是不可迭代的错误)。我想,我总是可以使用Webapp代码来更改数据,但我希望将其打包并准备就绪。
所以我找到了一些解决方案,但是什么都还没有。
为了使对象可下标,我将其添加到模型中:
def __getitem__(self, key):
return self.__dict__[key]
__tablename__ = "smogon_usage_stats"
并使Stats
类的get函数返回语句:
return {"data": {x["pokemon"]: x for x in result}}
但是那只给了我一个输出。我想这是技术上的改进。 (在尝试以下建议的答案时也得到了相同的结果
如果可能我遗漏了一些东西,我尝试简化它,并停止尝试只花一行,而它仍然给我一个输出。我已验证result
是长度为143
的列表。但是由于某种原因,我没有得到想要的结果,而且我的空间和创意都用光了。
class Stats(Resource):
@marshal_with(resource_fields)
def get(self, date, tier):
result = StatsModel.query.filter_by(date=date, tier=tier + "-1500").all()
resp = {"data":{}}
for i in range(len(result)):
t = {result[i]["pokemon"]: result[i]}
resp["data"].update(t)
return resp
,并且在我提出请求时返回此值:
{
'id_': 0,
'rank': 0,
'pokemon': None,
'usage_pct': None,
#... to save space but you get the idea
'tier': None
}
还要确保,我对迭代的对象进行了type()
检查,它们返回了<class '__main__.StatsModel'>
。
答案 0 :(得分:2)
我不确定这是否是最好的方法,但是它的工作方式与您想要的方式一样。
class Stats(Resource):
@marshal_with(resource_fields)
def get(self, date, tier):
result = StatsModel.query.filter_by(date=date, tier=tier + "-1500").all()
return {"data": list(map(lambda x: {x['pokemon']: x}, result))}
答案 1 :(得分:1)
尝试一下。这将从结果中读取每个元素,并将其保存到字典中。然后按照您的格式将此字典保存到另一个字典中:
import io
import base64
from PIL import Image
base64_str = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='
buffer = io.BytesIO()
imgdata = base64.b64decode(base64_str)
img = Image.open(io.BytesIO(imgdata))
new_img = img.resize((2, 2)) # x, y
new_img.save(buffer, format="PNG")
img_b64 = base64.b64encode(buffer.getvalue())
print(str(img_b64)[2:-1])
答案 2 :(得分:0)
我还没有使用过Flask-RESTful,但这似乎是一个简单的数据转换问题。
在交互式Python shell中:
>>> rowList = [
... {'id_': 669551, 'rank': 153, 'pokemon': 'snorunt', 'usage_pct': 0.07347, 'raw_usage': 104, 'raw_pct': 0.127, 'real': 96, 'real_pct': 0.148, 'dex': 361, 'date': '2020-04', 'tier': 'gen8lc-1500'},
... {'id_': 669552, 'rank': 154, 'pokemon': 'milcery', 'usage_pct': 0.0672, 'raw_usage': 108, 'raw_pct': 0.131, 'real': 87, 'real_pct': 0.134, 'dex': 868, 'date': '2020-04', 'tier': 'gen8lc-1500'},
... {'id_': 669553, 'rank': 156, 'pokemon': 'cosmog', 'usage_pct': 0.0199, 'raw_usage': 26, 'raw_pct': 0.032, 'real': 19, 'real_pct': 0.029, 'dex': 789, 'date': '2020-04', 'tier': 'gen8lc-1500'}
... ]
>>>
>>> transformed = {"data": {row['pokemon']: row for row in rowList}}
>>>
>>> import pprint
>>> pprint.pprint(transformed)
{'data': {'cosmog': {'date': '2020-04',
'dex': 789,
'id_': 669553,
'pokemon': 'cosmog',
'rank': 156,
'raw_pct': 0.032,
'raw_usage': 26,
'real': 19,
'real_pct': 0.029,
'tier': 'gen8lc-1500',
'usage_pct': 0.0199},
'milcery': {'date': '2020-04',
'dex': 868,
'id_': 669552,
'pokemon': 'milcery',
'rank': 154,
'raw_pct': 0.131,
'raw_usage': 108,
'real': 87,
'real_pct': 0.134,
'tier': 'gen8lc-1500',
'usage_pct': 0.0672},
'snorunt': {'date': '2020-04',
'dex': 361,
'id_': 669551,
'pokemon': 'snorunt',
'rank': 153,
'raw_pct': 0.127,
'raw_usage': 104,
'real': 96,
'real_pct': 0.148,
'tier': 'gen8lc-1500',
'usage_pct': 0.07347}}}
>>>
除非我缺少任何内容,否则看来transformed
正是您想要的。 (我想念什么?)
当然,您的代码中的result
不是list
,而上面的rowList
是。在这种情况下,请考虑首先将其转换为列表(并将包含的记录转换为字典)。
答案 3 :(得分:0)
仅需在它们之间进行更改
[
{"id_": 669551, "rank": 153, "pokemon": "snorunt", "usage_pct": 0.07347,
"raw_usage": 104, "raw_pct": 0.127, "real": 96, "real_pct": 0.148,
"dex": 361, "date": "2020-04", "tier": "gen8lc-1500"},
{"id_": 669552, "rank": 154, "pokemon": "milcery", "usage_pct": 0.0672,
"raw_usage": 108, "raw_pct": 0.131, "real": 87, "real_pct": 0.134,
"dex": 868, "date": "2020-04", "tier": "gen8lc-1500"},
{"id_": 669553, "rank": 156, "pokemon": "cosmog", "usage_pct": 0.0199,
"raw_usage": 26, "raw_pct": 0.032, "real": 19, "real_pct": 0.029,
"dex": 789, "date": "2020-04", "tier": "gen8lc-1500"}
]
和
{"data": {
"snorunt": {
"id_": 669551, "rank": 153, "pokemon": "snorunt", "usage_pct": 0.07347,
"raw_usage": 104, "raw_pct": 0.127, "real": 96, "real_pct": 0.148,
"dex": 361, "date": "2020-04", "tier": "gen8lc-1500"},
"milcery": {
"id_": 669552, "rank": 154, "pokemon": "milcery", "usage_pct": 0.0672,
"raw_usage": 108, "raw_pct": 0.131, "real": 87, "real_pct": 0.134,
"dex": 868, "date": "2020-04", "tier": "gen8lc-1500"},
"cosmog": {
"id_": 669553, "rank": 156, "pokemon": "cosmog", "usage_pct": 0.0199,
"raw_usage": 26, "raw_pct": 0.032, "real": 19, "real_pct": 0.029,
"dex": 789, "date": "2020-04", "tier": "gen8lc-1500"
}
}}
简单尝试
new_result = {"data": {}}
for item in dictionary:
new_result["data"][item["pokemon"]] = item
其中dictionary
是第一个,new_result
是第二个。
答案 4 :(得分:0)
import React , {useState, useEffect} from 'react';
const [userData, setUserData] = useState({});
useEffect(() => {
const getUser = async () => {
const response = await axios.get('api/babyinfo');
setUserData(response.data.data[0]);
}
getUser();
},[]);
return <span>{userData.name}</span>