Pass Flask route parameters into a decorator

2024/10/8 13:33:39

I have written a decorator that attempts to check we have post data for a Flask POST route:

Here's my decorator:

def require_post_data(required_fields=None):def decorator(f):@wraps(f)def decorated_function(*args, **kwargs):for required_field in required_fields:if not request.form.get(required_field, None):return jsonify({"error": "Missing %s from post data." %required_field}), 400else:if not request.form:return jsonify({"error": "No post data, aborting."}), 400return f(*args, **kwargs)return decorated_functionreturn decorator

And I have two routes, with with a URL param and the other without:

from flask import Blueprint, jsonify, requestmod = Blueprint('contacts', __name__, url_prefix='/contacts')@mod.route('/', methods=['POST'])
@require_post_data(['customer_id', 'some_other_required_field'])
def create_contact():# Do some business@mod.route('/<int:contact_id>', methods=['POST'])
@require_post_data
def update_contact(contact_id):# Do some business

When I run a test that hits update_contact, I'm getting the following exception:

TypeError: decorator() got an unexpected keyword argument 'contact_id'

But it looks like create_contact is working as expected.

Why is contact_id being passed into decorator()?

Answer

I believe you're just missing one thing, which is to actually call require_post_data to produce a decorator function in the update_contact route. This should fix it:

@mod.route('/<int:contact_id>', methods=['POST'])
@require_post_data() # <- note the parens
def update_contact(contact_id):# Do some business

The detailed explanation is that what you expected to happen (and what is happening in create contact) is that the the view function is being modified by the decorator produced by require_post_data. In your update_contact above, what is actually happening is that the view function is being passed to require_post_data itself and simply used as the value of the required_fields parameter. This doesn't cause an error so require_post_data happily returns decorator which is then routed to when you hit /<int>, causing it to be passed contact_id as a keyword argument, resulting in the error you saw.

https://en.xdnf.cn/q/70118.html

Related Q&A

update env variable on notebook in VsCode

I’m working on a python project with a notebook and .env file on VsCode. I have problem when trying to refresh environment variables in a notebook (I found a way but its super tricky). My project: .en…

How do I properly set up flask-admin views with using an application factory?

Im trying to setup flask-admin model views with SQLAlchemy against user and role models. Instead of a function admin view Im getting:ValueError: Invalid model property name <class app.models.Role>…

Django Rest Framework: Correct way to serialize ListFields

Based on the DRF documentation I have a created a list of email_id stored in my model in the following way Models.pyclass UserData(models.Model):emails = models.CharField(max_length=100,blank=False)In…

Flask-SQLAlchemy TimeoutError

My backend configuration is :Ubuntu 12.04 Python 2.7 Flask 0.9 Flask-SQLAlchemy Postgres 9.2Ive got this error message: TimeoutError: QueuePool limit of size 5 overflow 10 reached, connection timed ou…

Making saxon-c available in Python

I have just read that Saxon is now available for Python, and thats just great fun and good, but can anyone write a tutorial on how to make it available for Python/Anaconda/WingIDE or similar? I am use…

How to include multiple interactive widgets in the same cell in Jupyter notebook

My goal is to have one cell in Jupyter notebook displaying multiple interactive widgets. Specifically, I would like to have four slider for cropping an image and then another separate slider for rotati…

SWIG - Problem with namespaces

Im having trouble getting the following simple example to work with SWIG 1.3.40 (and I also tried 1.3.31). The Foo structure comes through as a Python module as long as I dont wrap it in a namespace, b…

Django access to subclasses items from abstract class

class Animal(models.Model):....class Meta:abstract = Trueclass Cat(models.Model, Animal):...class Dog(models.Model, Animal):....I want to be able to return all instances of querysets of all the subclas…

Django BinaryField retrieved as memory position?

Ive written a short unit test with the following code:my_object = MyObject() my_object.data = b12345my_object.save() saved_object = MyObject.objects.first()assert saved_object.data == my_object.datawhe…

difflib.SequenceMatcher isjunk argument not considered?

In the python difflib library, is the SequenceMatcher class behaving unexpectedly, or am I misreading what the supposed behavior is?Why does the isjunk argument seem to not make any difference in this…