Form and JSON Post Request Value to Model Mapper Functions For Flask
One of the iritating part that you have to deal with when you're handling POST requests in Flask is how you map the values into the model. It could be in JSON or in common form format.
Usually this is what you do
Using these helpers, all you need to do for the previous request is way simpler.
Neat codes, eh? And no matter how many attributes in your class, it is that simple. You can also use this for handling edit operations. Simply passed in the object having query results into the parser functions.
Have a better and more DRY code? Great news! Hope this helps.
Btw, I'll be shipping these methods with my EmeraldBox framework very soon, while my backyard framework already has it :)
regards
-E-
follow @femmerling on twitter
visit my website
Usually this is what you do
# say this is your modelThat's if the model has 5 properties, what if you have more than 10 or perhaps more than 20 properties? That would be tedious. We should try making it simple and DRY, right? I wrote helper functions to help you simplify it.
# using SQLAlchemy
class User(db.Model):
username = db.Column(db.String(50))
password = db.Column(db.String(50))
email = db.Column(db.String(50))
first_name = db.Column(db.String(50))
last_name = db.Column(db.String(50))
# this handles the common form request
app.route('/process_form',methods=['POST'])
def data_process():
new_user = User(
username = request.values.get('username')
password = request.values.get('password')
email = request.values.get('email')
first_name = request.values.get('first_name')
last_name = request.values.get('last_name')
)
# okay and then you do the rest
# or perhaps JSON post request handling
app.route('/process_json',methods=['POST'])
def data_process():
data = json.loads(request.data)
new_user = User(
username = data['username']
password = data['password']
email = data['email']
first_name = data['first_name']
last_name = data['last_name']
)
# okay and then you do the rest
import json
def new_json_parser(passed_object, payload_data):
"""
Maps passed json object from client into expected object.
Use this for creation of new object by passing an instantiated
empty object into the passed_object variable
"""
payload = json.loads(payload_data)
for key, value in payload.items():
if hasattr(passed_object, key):
setattr(passed_object, key, value)
return passed_object
# this part is for form request value handling
def new_form_parser(passed_object, request_data):
"""
Maps form request object from client into expected object.
Use this for creation of new object by passing an instantiated
empty object into the passed_object variable
"""
for item in request_data.values:
if hasattr(passed_object, item) and request_data.values.get(item):
setattr(passed_object, item, request_data.values.get(item))
return passed_object
Using these helpers, all you need to do for the previous request is way simpler.
# using form
app.route('/process_form',methods=['POST'])
def data_process():
new_user = User()
new_user = new_form_parser(new_user, request)
# and there you go, your new user object based on form post request is ready
#using json
app.route('/process_json',methods=['POST'])
def data_process():
new_user = User()
new_user = new_json_parser(new_user, request.data)
# and there you go, your new user object based on json post request is ready
Neat codes, eh? And no matter how many attributes in your class, it is that simple. You can also use this for handling edit operations. Simply passed in the object having query results into the parser functions.
def edit_json_parser(passed_object, payload_data):
"""
Maps value from passed json object for data edit purposes.
You need to pass in object resulting from query into the
passed_object variable
"""
payload = json.loads(payload_data)
for key, value in payload.items():
if key != "id" and value != None:
if hasattr(passed_object, key):
setattr(passed_object, key, value)
return passed_object
def edit_form_parser(passed_object, request_data):
"""
Maps value from passed json object for data edit purposes.
You need to pass in object resulting from query into the
passed_object variable
"""
for item in request_data.values:
if item != "id" and hasattr(passed_object, item) and request_data.values.get(item):
setattr(passed_object, item, request_data.values.get(item))
return passed_object
Have a better and more DRY code? Great news! Hope this helps.
Btw, I'll be shipping these methods with my EmeraldBox framework very soon, while my backyard framework already has it :)
regards
-E-
follow @femmerling on twitter
visit my website
Hi,
ReplyDeleteI think if we use Flask-WTF, we can solve this easily using .populate_obj method of form object. Don't you think so?
This is my code that handle Json form POST request : https://github.com/CoderDojoIndonesia/bio/blob/master/wsgi/main.py#L261
I paste it in full here :
@application.route('/portfolio_add_update', methods = ['POST'])
@login_required #how to protect this in ajax called only for signed user?
def portfolio_add_update():
form = PortoForm(request.form)
if form.validate():
result = {}
result['iserror'] = False
if not form.portfolio_id.data:
user = Users.query.filter_by(username = session['username']).first()
if user is not None:
user.portfolio.append(Portfolio(title = form.title.data, description = form.description.data, tags = form.tags.data))
print 'id ', form.portfolio_id
db.session.commit()
result['savedsuccess'] = True
else:
result['savedsuccess'] = False
else:
portfolio = Portfolio.query.get(form.portfolio_id.data)
form.populate_obj(portfolio)
db.session.commit()
result['savedsuccess'] = True
return json.dumps(result)
form.errors['iserror'] = True
print form.errors
return json.dumps(form.errors)
Well, that works too and you can use it if you want. I write this one simply because I dont want to use another extension and makes it simpler and lighter to run :)
ReplyDeleteGood post. Thank you.
ReplyDelete