Python flask_restful arguments - python

I'm creating the server end of a test API using flask_restful that will capture a request coming into the API with a ID, and 3 parameters. If the Id does not exists, then it is created and populated with the 3 data arguments. The Asset is created, however only the 3rd parameter is added to the dict.
Code I have:
from flask import Flask, request
from flask_restful import reqparse, abort, Api, Resource
app = Flask(__name__)
api = Api(app)
assets = {}
def abort_if_asset_doesnt_exist(asset_id):
if asset_id not in assets:
abort(404, message="Asset {} doesn't exist".format(asset_id))
parser = reqparse.RequestParser()
parser.add_argument('data1', type=str)
parser.add_argument('data2', type=str)
parser.add_argument('data3', type=str)
class Asset(Resource):
def get(self, asset_id):
return {asset_id: assets[asset_id]}
def put(self, asset_id):
assets[asset_id] = request.form['data1']
assets[asset_id] = request.form['data2']
assets[asset_id] = request.form['data3']
return {asset_id: assets[asset_id]}
def delete(self, asset_id):
abort_if_todo_doesnt_exist(asset_id)
del assets[asset_id]
return '', 204
api.add_resource(Asset, '/api-v1.0/add/<string:asset_id>', methods=['PUT', 'GET'])
if __name__ == '__main__':
app.run(debug=True)
I want to take the id and create a 'instance' in the dictionary, with it's corresponding data fields attached to it. like below
What I want:
{
"123456" {
"data1":"Mydata1"
"data2":"Mydata2"
"data3":"Mydata3"
}
}
With this I can call the asset and receive it's associated data fields.
The curl (PUT) command I use looks like this.
$ curl http://localhost:5000/api-v1.0/add/123456 -d "data1=Mydata1" -d "data2=Mydata2" -d "data3=Mydata3" -X PUT

This is because you're just assigning a value one after the other to the location specified by asset_id in your assets dict. Since the last value assigned to assets is the 3rd parameter this is the value that is contained at that key.
To fix this you need to change that code to create a dict for the asset_id that you want to store the form data against:
assets[asset_id] = dict()
assets[asset_id]['data1'] = request.form['data1']
assets[asset_id]['data2'] = request.form['data2']
assets[asset_id]['data3'] = request.form['data3']
Or even better use a defaultdict:
assets = defaultdict(dict)
...
assets[asset_id]['data1'] = request.form['data1']

Related

Issue with bad request syntax with flask

I am testing/attempting to learn flask, and flast_restful. This issue I get is:
code 400, message Bad request syntax ('name=testitem')
main.py:
from flask import Flask,request
from flask_restful import Api, Resource, reqparse
app = Flask(__name__)
api = Api(app)
product_put_args = reqparse.RequestParser()
product_put_args.add_argument("name", type = str, help = "Name of the product")
product_put_args.add_argument("quantity", type = int, help = "Quantity of the item")
products = {}
class Product(Resource):
def get(self, barcode):
return products[barcode]
def put(self, barcode):
args = product_put_args.parse_args()
return {barcode: args}
api.add_resource(Product, "/product/<int:barcode>")
if(__name__) == "__main__":
app.run(debug = True)
and my
test.py
import requests
base = "http://127.0.0.1:5000/"
response = requests.put(base + "product/1", {"name": "testitem"})
print(response.json())
I have attempted to reform mat and change around both files to figure out what is sending the issue, I feel like it is something simple, but if you can help me, I bet this will help me and many others that are trying to start creating a rest API.
You need to add the location information to the RequestParser by default it tries to parse values from flask.Request.values, and flask.Request.json, but in your case, the values need to be parsed from a flask.request.form. Below code fixes your error
from flask import Flask,request
from flask_restful import Api, Resource, reqparse
app = Flask(__name__)
api = Api(app)
product_put_args = reqparse.RequestParser()
product_put_args.add_argument("name", type = str, help = "Name of the product", location='form')
product_put_args.add_argument("quantity", type = int, help = "Quantity of the item", location='form')
products = {}
class Product(Resource):
def get(self, barcode):
return products[barcode]
def put(self, barcode):
args = product_put_args.parse_args()
products[barcode] = args['name']
return {barcode: args}
api.add_resource(Product, "/product/<int:barcode>")
if(__name__) == "__main__":
app.run(debug = True)

Problem with POST Method on my Flask APP on Python

i have a problem with my flask app thaht i'm trying to create,
i wrote a POST Method to take arguments from HTTP and write them to a table.
here's my code:
from flask import Flask
from flask_restful import Resource, Api, reqparse
import pandas as pd
import ast
import sqlalchemy
# SQLAlchemy connectable
engine = sqlalchemy.create_engine("mssql+pymssql://my_connection_string")
conn = engine.connect()
app = Flask(__name__)
api = Api(app)
class Samples(Resource):
def get(self):
data = pd.read_sql_table('DBLIST_DATA', engine)
data = data.to_dict() # convert dataframe to dict
return {'data': data}, 200 # return data and 200 OK
def post(self):
parser = reqparse.RequestParser() # initialize
parser.add_argument('NODE_NO_data', required=True) # add args
parser.add_argument('BLOCK_NAME_data', required=True)
parser.add_argument('BLOCK_TYPE_data', required=True)
args = parser.parse_args() # parse arguments to dictionary
# read our SQL Table
data = pd.read_sql_table('DBLIST_DATA', engine)
#Check if Value Exists
if args['NODE_NO_data'] in list(data['NODE_NO_data']):
return {
'message': f"'{args['NODE_NO_data']}' already exists."
}, 409
else:
# create new dataframe containing new values
new_data = pd.DataFrame({
'NODE_NO_data': [args['NODE_NO_data']],
'BLOCK_NAME_data': [args['BLOCK_NAME_data']],
'BLOCK_TYPE_data': [args['BLOCK_TYPE_data']],
'locations': [[]]
})
# add the newly provided values
data = data.append(new_data, ignore_index=True)
data.to_sql('DBLIST_DATA', index=False) # save back to SQL Table
return {'data': data.to_dict()}, 200 # return data with 200 OK
api.add_resource(Samples, '/samples') # add endpoints
if __name__ == '__main__':
app.run() # run app
when i try to POST via Postman the following values:
127.0.0.1:5000/samples/?NODE_NO_data=1&BLOCK_NAME_data=Machine&BLOCK_TYPE_data=Vertical
i'm getting a 404 not found error.
can someone please tell me what i'm doing wrong?
Thanks!
You could just remove the last / of your request URL http://127.0.0.1:5000/samples.

Get json api data from another api flask

i created this rest api with flask and sql alchemy and i want to not enter the json data manually but get it from another json and add it to my database :
https://www.habitat.fr/api/qDbBye4V7vtMu8qL97vvHTAnLQuEhC/product/911095/sku
my add product route in flask
#add product
#app.route('/product', methods=['POST'])
def add_product():
name = request.json['name']
description = request.json['description']
price = request.json['price']
qty = request.json['qty']
new_product = Product(name,description,price,qty)
db.session.add(new_product)
db.session.commit()
return product_schema.jsonify(new_product)
All you need do is write a function using requests and json modules to fetch the json in the url like this:
import requests
import json
def get_data():
r = requests.get('https://www.habitat.fr/api/qDbBye4V7vtMu8qL97vvHTAnLQuEhC/product/911095/sku')
return json.loads(r.content) #convert content to dict
You may now call the function in your flask app:
#app.route('/product', methods=['POST'])
def add_product():
my_data = get_data()
name = my_data['name']
description = my_data['description']
price = my_data['price']
qty = my_data['qty']

How to use SELECT query based on method parameter in Flask restplus Api?

I want to handle a GET request in my Flask REST API.The request will include List parameter and I use this to be a typical GET request:
https://localhost:5000/organisation?List=1
this request, will return all of Organisation Model information. Organisation is a Model class for a table of my MySQL database(by peewee).
I want to enter PrivenceId parameter in request and will return all of Organisation Model information where Organisation.PrivencedId == PrivenceId parameter, But I encounter the following Error:
TypeError: 'Organisation' object is not iterable
my code (OrganisationController.py file) is:
from flask_restplus import Resource, reqparse
from Models.Organisation import Organisation
from flask import request
# Define parser and request args
parser = reqparse.RequestParser()
parser.add_argument('List', type=int)
parser.add_argument('ProvinceId', type=int)
class List(Resource):
def get(self):
args = parser.parse_args()
List = args['List']
ProvinceId = args['ProvinceId']
if List :
Organisations = Organisation.select()
Ls = [dict (
ID = c.ID,
Title = c.Title,
Code = c. Code,
OrgEnumId = c.OrgEnumId,
ProvinceId = c.ProvinceId,
CityId = c.CityId,
Address = c.Address,
Phone = c.Phone,
) for c in Organisations
]
return dict(Organisations = Ls)
elif (ProvinceId) :
Organisations = Organisation.select().where
(
Organisation.ProvinceId ==args['ProvinceId']
).get()
Ls = [dict (
ID = c.ID,
Title = c.Title,
Code = c. Code,
OrgEnumId = c.OrgEnumId,
ProvinceId = c.ProvinceId,
CityId = c.CityId,
Address = c.Address,
Phone = c.Phone,
) for c in Organisations
]
return dict(Organisations = Ls)
and boot.py file for run api is :
from flask import Flask
from flask_restplus import Api
from Controllers import OrganisationController
app = Flask(__name__)
api = Api(app)
api.add_resource(OrganisationController.List, '/organisation')
if __name__ == "__main__":
app.run ('127.0.0.1', 5000, True)
Could you help me?
I changed this line of my code and solved my problem:
Organisations = Organisation.select().where
(
Organisation.ProvinceId ==args['ProvinceId']
)

Python / Flask / MongoEngine DateTimeField

First of I'm new to python and flask. I've searched around and tried something things to no avail. I have a model that has a DateTimeField as one of the members, let's call it "created_at". When I go to return the query set as JSON I see this for the field
...
"created_at": {
"$date": 1412938697488
}
...
Is there anyway to get the output, either through a custom JSON encoder, etc to get it to look like this :
"created_at": "2014-10-10T07:33:04Z",
Any guidance or suggestions would be greatly appreciated.
Thanks!
Here is an example using flask and flask-mongoengine to get a date as ISO 8601 string
import datetime
from bson.json_util import dumps
from flask import Flask, Response, request
from flask_mongoengine import MongoEngine
app = Flask(__name__)
db = MongoEngine()
class Movie(db.Document):
name = db.StringField(required=True, unique=True)
casts = db.ListField(db.StringField(), required=True)
genres = db.ListField(db.StringField(), required=True)
created_at = db.DateTimeField(default=datetime.datetime.utcnow)
#app.route('/movies')
def get_movies():
movies = Movie.objects()
movies_list = []
for movie in movies:
movie_dict = movie.to_mongo().to_dict()
movie_dict['created_at'] = movie.created_at.isoformat()
movies_list.append(movie_dict)
movies_josn = dumps(movies_list)
return Response(movies_josn, mimetype="application/json", status=200)
#app.route('/movies', methods=['POST'])
def add_movie():
body = request.get_json()
movie = Movie(**body).save()
id = movie.id
return {'id': str(id)}, 200
if __name__ == '__main__':
app.config['MONGODB_SETTINGS'] = {
'host': 'mongodb://localhost/movie-bag'
}
db.init_app(app)
app.run()

Categories