how to change flask default http method from GET to POST - python

currently flask use GET as default HTTP method, is there any flexible way to change this default method to POST for all app.route?

The only way I can think to do this would be to run your own version of Flask that changes this code to default to a POST
# if the methods are not given and the view_func object knows its
# methods we can use that instead. If neither exists, we go with
# a tuple of only ``GET`` as default.
if methods is None:
methods = getattr(view_func, 'methods', None) or ('GET',)
becomes...
# if the methods are not given and the view_func object knows its
# methods we can use that instead. If neither exists, we go with
# a tuple of only ``GET`` as default.
if methods is None:
methods = getattr(view_func, 'methods', None) or ('POST',)
Code: Lines 1184-1188
Though at this point it's probably just simpler to add a method declaration of POST to each route definition.

Related

How to determine if an argument was passed with a gRPC call or not?

Question: When parsing a gRPC call's request in my gRPC endpoint, how can I make use of a certain request.<attribute> only if it was explicitly passed with the gRPC call?
I have this in my .proto:
message Object {
bool enabled = 1;
}
I have this as my endpoint:
class CRUDService(CRUDServicer):
#staticmethod
def Create(request: Object_pb2.CreateReq, context) -> Object_pb2.CreateResp:
options = {}
if request.enabled:
options["enabled"] = request.enabled
obj = create_obj(options)
return Object_pb2.CreateResp(serialized_obj=serialize(obj))
However, the if-condition does not check if enabled was passed with the call or not. It turns out enabled is always accessible on the request object. And with the snippet above, I will make it impossible to set options = {"enabled": False}, which I want to be able to do.
So, when querying request.enabled, I will get one of:
The default value, explicitly passed with the call
The default value, not passed with the call
The non-default value, explicitly passed with the call
To further illustrate the problem, imagine setting up an Update endpoint (for the U in CRUD). Then I only want to update with whatever request fields were actually passed with the gRPC call - and not just update with a default value of something which was not even passed with the call.

How to change routes in Flask?

I have watched a tutorial on Flask and I can't seem to understand how does this code work
def my_home():
return render_template("./index.html")
#app.route('/<string:page_name>')
def html_page(page_name):
return render_template(page_name)```
Specifically /<string:page_name> is confusing to me, how does it understand what is page_name and redirect to that page?
Thank you!
The answer to this is in the magic of decorators and not flask itself. A decorator is a high level function which accepts a function and manipulates it accordingly. See the following example:
def route(func, user_path):
# internal flask mechanisms here
def callback(user_path):
return http.route(user_path, func)
return callback
#route("hello_world")
def render():
return "Hello World"
The decorator is taking your function as an input and performing some actions to correlate the path with your given input. This can obviously be used for many other purposes. For example, flask also allows an additional decorator to define the type of request allowed for the function, such as GET, POST, etc.
To answer your question, flask is accepting a URL parameter and generating the page based on that given parameter. This is known as dynamic routing and is used for database query purposes based on the route (though the given example is trivial). So if someone goes to page_name "John", you can use that value and template it in your html to dynamically say hi to John (and whomever else).
/<string:page_name>
means that Flask expects a customised string after your domain i.e.
www.yourdomain.com/anycustomisedstring
/<data_type:your_variable_name> i.e. /<integer:page_number>
in this case, your variable is passed as a parameter to your function. This function returns the site that is passed in the URL as a string

Odoo 11+ How to override function args and all calls to it without overriding every call

I want to override the uom._compute_price() and compute_quantity() in odoo to add product as an argument.
the problem is that these functions are called in many other functions in many other modules like stock, account, sale, purchase.
So I have to override each calling function which is about 140 occurrences .
Is there a better way to implement this without modifying the 140 calls ?
for ex. in the overridden functions, can I get the original caller object and its attributes ?
If there is a way to get the product from self or any other object, you can
make product_id a keyword only argument and check
it's not None, else you set it your self from an object.
def _compute_price(self, same_arguments,*,product_id=None)
if product_id is None:
product_id = # get the id from something
# your code here
If you can't get the product_id from anywhere I hope you find
and solution for that or you have to edit all calls.
Changing an upstream method arguments is not recommended, and you are discovering the why.
However, your calls to it can add a key in the context, and the overridden method can react to it. Example:
def _compute_price(self, original_args):
if self.env.context.get("product_id"):
# Do your stuff here
return super()._compute_price(original_args)
Then, from other parts of your module, call the method with that context key:
uom.with_context(product_id=product.id)._compute_price(original_args)
Another option would be to add the context key in the overriden method itself, if you want it to be present under every call:
def _compute_price(self, original_args):
# Get the product somehow here
return super(type(self), self.with_context(product_id=product.id))._compute_price(original_args)
However, keep in mind that only addons that are aware of this context and react to it actually need it. The 1st approach should be the most accurate for most cases.

Unittest sensitive_post_parameters decorator in django view

I have a view to create new users in my django project.
I am applying the #sensitive_post_parameters decorator to that view to make sure the password isn't logged if there is an unhandled exception or something like that (as indicated in the comments in the source code https://docs.djangoproject.com/en/2.0/_modules/django/views/decorators/debug/).
When I proceed to test the view, I would like to make sure that this protection of the sensitive information is still in place (that I didn't delete the decorator to the function by mistake or something).
I am aware, since the decorator is applied to my function, I can't test it directly from the view tests.
But, for example, with the #login_required decorator, I can test its effects with assertRedirects (as explained here How to test if a view is decorated with "login_required" (Django)).
I have been searching for a way to do that, but I can't find one that works.
I thought of something like this:
def test_senstive_post_parameters(self):
request = RequestFactory().post('create_user', data={})
my_sensitive_parameters = ['password']
self.assertEqual(
request.sensitive_post_parameters,
my_senstive_parameters
)
but that gives me an
AttributeError: 'WSGIRequest' object has no attribute 'sensitive_post_parameters'
Any help would be appreciated.
Even it is telling me I shouldn't be attempting to test this, though I would really like to, as it is seems like an important behaviour that I should make sure remains in my code as it is later modified.
You have created a request using RequestFactory, but you have not actually used it. To test the effect of your view you need to import the view and call it.
from myapp.views import create_user
def test_senstive_post_parameters(self):
request = RequestFactory().post('create_user', data={})
response = create_user(request)
my_sensitive_parameters = ['password']
self.assertEqual(
request.sensitive_post_parameters,
my_senstive_parameters
)

Python Werkzeug: modify Request values (forms and args) prior to retrieval

Is there a way in Werkzeug to edit the request values (forms and args) before using it?
I need to encode the request values from utf8 to iso88591. I created a function to handle this.
I would like to use this function on all form values so that I avoid the second line of the following:
lcl_var = request.form['post_arg']
lcl_var = encode_utf8_to_iso88591(lcl_var)
I couldn't figure out what I needed from the Werkzeug docs. I imagine there's a way to subclass the Request class and override a one of its methods that handles the values. Would really appreciate a concrete example on how to implement this well.
A limited example exists on extending request parsing at the Werkzeug docs. It's a little buried, but it's sound.
http://werkzeug.pocoo.org/docs/request_data/#how-to-extend-parsing
Since Werkzeug is a pretty low-level tool over HTTP, this functionality could also be implemented in your request dispatcher (assuming a structure similar to the one in the Werkzeug tutorial, the function that applies the url map to the request.)
EDIT:
It seems that per the Werkzeug docs, the best way to do this is to process your own request property out of the stream. It'd be nice to do this is a way that preserves the immutability of the request.form property:
def encode(value):
#Your logic for the new dict vals
return 'foo!'
class MixInRequest(Request):
max_content_length = 1024 * 1024 * 4
#cached_property
def lcl_data(self):
if self.method in ['POST','PUT','PATCH']:
fields = dict([(key, encode(val)) for (key,val) in self.form.items()])
return ImmutableMultiDict(fields)
return None
This sets a request property lcl_data (named after your function) that will parse on first access and cache for subsequent calls. It only functions for methods that would populate request.form.
Full example here:
https://gist.github.com/DeaconDesperado/7292574

Categories