Any good working example for webapp2 using http put method? - python

I would like to use HTTP PUT method , to send data to my google app engine application, any good example? I can't find any from google.
And my following example also not working.
import webapp2
class MainHandler(webapp2.RequestHandler):
def put(self):
self.response.write('test put')
app = webapp2.WSGIApplication([
(r'/test/(.*)', MainHandler)
], debug=True)
And i got this error.
TypeError: put() takes exactly 1 argument (2 given)

you are passing the put an argument with mapping it like this:
(r'/test/(.*)', MainHandler)
the (.*) passes the put method whatever you use to access this urlpath after /test/.
update your handler like this:
class MainHandler(webapp2.RequestHandler):
def put(self, myarg):
self.response.write('test put, myarg is %s' %myarg)

TypeError: put() takes exactly 1 argument (2 given)
Means that the method 'put' was called with 2 arguments while you specified only 1 (self).
This should work:
class MainHandler(webapp2.RequestHandler):
def put(self, param):
self.response.write('test put')

You can using POST variable from request object
class MainHandler(webapp2.RequestHandler):
def put(self):
self.response.write(self.request.POST)
example usage using curl
curl -X PUT -d"x=1&y=2" http://localhost:8080/add

Related

How to access class object inside the class in flask?

I've got flask running in a class
from flask import Flask
class Server:
app = Flask(__name__)
def __init__(self, object_with_data):
self.object = object_with_data
#app.route("/")
def hello(self):
return self.object.get_data()
def run():
self.app.run(host='0.0.0.0')
but I get an error saying
TypeError: hello() missing 1 required positional argument: 'self'.
How do I get access to an instance of the object when running flask within a class?
One dirty solution I thought of was using sockets to create a link between my server class and the object_with_data class, but I'm sure someone will know a better way to do this.
I read something about event handlers, but I don't fully understand that.

Decorator isn't getting arguments

I'm trying to add an access_rights decorator to my Bottle app to check permissions when accessing a route. However, it's not getting the decorated function's arguments, which causes an error when trying to call my decorated function again.
Here's an example of code using the decorator:
#route('/users')
#access_rights({'POST': ['admin']})
def users(user):
pass
The user parameter comes from a Bottle plugin I wrote that gets the user from the token passed with the request. This is my current decorator:
def access_rights(permissions):
def decorator(f):
def wrapper(*args, **kwargs):
# Check permissions rights here (not implemented yet)
return f(*args, **kwargs)
return wrapper
return decorator
With this, I get TypeError: users() takes exactly 1 argument (0 given) when doing a GET /users, meaning args and kwargs were both empty. However, when I change the decorator as follows, it works:
def access_rights(permissions):
def decorator(f):
return f
return decorator
I haven't worked with decorators a lot, but from my understanding, both implementations above should call the users function with its original parameters, yet for some reason the first one doesn't get the parameters. Why is that?
Your route handler, function users, expects one parameter.
But your decorator, access_rights, which you wrap around users, isn't passing a user param; it's just passing any params that it received (and, in this case, there aren't any, hence the "0 given" part of the error message).
An example should help clarify. Here's a small but complete working app, based on your original code:
from bottle import route, Bottle
app = Bottle()
def access_rights(permissions):
def decorator(f):
def wrapper(*args, **kwargs):
# Check permissions rights here (not implemented yet)
the_user = 'ron' # hard-coded for this example
return f(the_user, *args, **kwargs)
return wrapper
return decorator
#app.route('/users')
#access_rights({'POST': ['admin']})
def users(user):
return ['hello, {}'.format(user)]
app.run(host='127.0.0.1', port=8080, debug=True)
Note that the only substantial change I made was to have access_rights actually pass a user param on down the line. (How it determines the user is, naturally, up to you--presumably it's the "not implemented yet" part that you called out in your comment).
Hope that helps!

What is being inherited by class flask.views.MethodView?

Why are we passing flask.views.MethodView in the class?
app.add_url_rule > in this snippet, add_url_rule is this something predefined property?
Similarly view_func, View.as_view > are they predefined?
import flask, flask.views
app = flask.Flask(__name__)
class View(flask.views.MethodView):
def get(self):
return "Hello World!"
app.add_url_rule('/',view_func=View.as_view('main'))
app.debug = True
app.run()
View is a subclass of the flask.views.MethodView class. The latter provides base functionality, like the as_view() method:
Converts the class into an actual view function that can be used with the routing system. Internally this generates a function on the fly which will instantiate the View on each request and call the dispatch_request() method on it.
Also see Pluggable Views.
Because this is not a function-based view, you cannot use the #app.route() decorator on it. You use the alternative app.add_url_rule() method instead in that case:
Connects a URL rule. Works exactly like the route() decorator. If a view_func is provided it will be registered with the endpoint.
view_func is a documented keyword argument for this method; when the registered path is requested (in your example /), then whatever as_view() returned is called by Flask. That in turn calls dispatch_request(), which then calls the View().get() method if the HTTP request used a GET method.

TypeError on CORS for flask-restful

While trying the new CORS feature on flask-restful, I found out that the decorator can be only applied if the function returns a string.
For example, modifying the Quickstart example:
class HelloWorld(restful.Resource):
#cors.crossdomain(origin='*')
def get(self):
return {'hello': 'world'}
Throws:
TypeError: 'dict' object is not callable
Am I doing something wrong?
I recently came across this issue myself. #MartijnPieters is correct, decorators can't be called on single methods of the view.
I created an abstract base class that contained the decorator list. The class that consumes Resource (from flask-restful) also inherits the base class, which is the class actually applying the decorator list to the view.
class AbstractAPI():
decorators = [cors.crossdomain(origin='*')]
class HelloWorld(restful.Resource, AbstractAPI):
#content
nope.
just add the decorator list to the parameters after you create the Api instance
api = Api(app)
api.decorators=[cors.crossdomain(origin='*')]
The return value of the wrapped function is passed (as one argument) to flask.make_response(); anything that a normal Flask view can return is acceptable. The decorator is essentially the same as this Flask snippet.
Because the Flask-restful Resource is a subclass of flask.views.MethodView you should really not put decorators directly on the methods here. As documented in Decorating Views you should list view decorators in a special class attribute, decorators which is a list:
class HelloWorld(restful.Resource):
decorators = [cors.crossdomain(origin='*')]
def get(self):
return {'hello': 'world'}
and Flask will apply the view to the actual view method returned by HelloWorld.as_view(), which is what Flask actually calls when dispatching the route to the view.
Applying them directly to the methods will only server to confuse the restful.Resource dispatcher as it is expecting methods to return python datastructures suitable for encoding to JSON, which is not what cors.crossdomain() returns anyway.
I found that you can still use the decorator provided you return a string or JSON response (which is probably good practice for an API anyway). This is important if you want to do route-specific CORS headers, using the decorator makes life much easier. See this merged pull req for more information: https://github.com/flask-restful/flask-restful/pull/131
Here's an example:
from . import app
from flask_restful import reqparse, abort, Api, Resource
from flask.ext.cors import cross_origin
from datetime import datetime
from flask import jsonify
api = Api(app)
class DateTime(Resource):
#cross_origin(origins="http://localhost:63342*")
def get(self):
return jsonify({'DateTime': str(datetime.today())})
api_root = '/api/v1/'
api.add_resource(DateTime, api_root + 'DateTime')
If you're using flask-security, adding auth decorators had some weird behavior in my testing. I recommend assert current_user.is_authenticated instead. If you are allowing credentials, make sure to CSRF protect.

Call external function without sending 'self' arg

I'm writing tests for a Django application and using a attribute on my test class to store which view it's supposed to be testing, like this:
# IN TESTS.PY
class OrderTests(TestCase, ShopTest):
_VIEW = views.order
def test_gateway_answer(self):
url = 'whatever url'
request = self.request_factory(url, 'GET')
self._VIEW(request, **{'sku': order.sku})
# IN VIEWS.PY
def order(request, sku)
...
My guess is that the problem I'm having is caused because since I'm calling an attribute of the OrderTests class, python assumes I wanna send self and then order get the wrong arguments. Easy to solve... just not use it as a class attribute, but I was wondering if there's a way to tell python to not send self in this case.
Thanks.
This happens because in Python functions are descriptors, so when they are accessed on class instances they bind their first (assumed self) parameter to the instance.
You could access _VIEW on the class, not on the instance:
class OrderTests(TestCase, ShopTest):
_VIEW = views.order
def test_gateway_answer(self):
url = 'whatever url'
request = self.request_factory(url, 'GET')
OrderTests._VIEW(request, **{'sku': order.sku})
Alternatively, you can wrap it in staticmethod to prevent it being bound to the instance:
class OrderTests(TestCase, ShopTest):
_VIEW = staticmethod(views.order)
def test_gateway_answer(self):
url = 'whatever url'
request = self.request_factory(url, 'GET')
self._VIEW(request, **{'sku': order.sku})

Categories

Resources