I'd like to do something like this:
class Basehandler(webapp.RequestHandler):
def __init__(self):
if checkforspecialcase: #check something that always needs to be handled
return SpecialCaseHandler.get()
class NormalHandler(Basehandler):
def get(self):
print 'hello world'
return
class SpecialCaseHandler(Basehandler):
def get(self):
print 'hello special world'
return
The idea is that no matter what handler is initially called, if a certain case is met, we basically switch to another handler.
I'm pretty new to python, so I'm not sure whether what I'm trying to do is possible. Or whether this is the best approach. What I'm really trying to do is make sure to show someone the complete-your-profile page if they've started the registration process but haven't completed it... no matter what request they're making. So the "checkforspecialcase" looks at their sessions and checks for incomplete info.
To keep things DRY, use the Template Method pattern
class BaseHandler(webapp.RequestHandler):
def DoGet(self, *args):
''' defined in derived classes, actual per-handler get() logic'''
pass
def get(self, *args):
# don't get caught in endless redirects!
if specialCase and not self.request.path.startswith('/special'):
self.redirect('/special')
else:
self.DoGet(*args)
class NormalHandler(BaseHandler):
def DoGet(self, *args):
# normal stuff
class SpecialHandler(BaseHandler):
def DoGet(self, *args):
# SPECIAL stuff
WSGIApplication routes incoming requests based on the URL. For example,
application = webapp.WSGIApplication(
[('/special-case', SpecialCaseHandler)])
When checkforspecialcase passes, you can use self.redirect('/special-case').
Your Basehandler could just implement a get() that checks for the special case and either redirects or calls self.view(), and each handler could implement view() (or whatever you'd like to call it) rather than get().
I'm not really into writing a class for each of my handlers, or using inheritance so conspicuously, so I'd recommend rolling decorators like these:
routes = []
def get (route):
def makeHandler (handle, *args, **kwargs):
class Handler (webapp.RequestHandler):
def get (self, *args, **kwargs):
shouldRedirectToCompleteProfile = # do your test
if shouldRedirectToCompleteProfile:
self.redirect('/special-case')
else:
handle(self, *args, **kwargs)
routes.append((route, Handler))
return Handler
return makeHandler
def post (route):
def makeHandler (handle, *args, **kwargs):
class Handler (webapp.RequestHandler):
def post (self, *args, **kwargs):
handle(self, *args, **kwargs)
routes.append((route, Handler))
return Handler
return makeHandler
#get('/')
def home (ctx):
# <...>
#get('/whatever/(.*)/(.*)')
def whatever (ctx, whatever0, whatever1):
# <...>
#post('/submit')
def submit (ctx):
# <...>
application = webapp.WSGIApplication(routes)
Related
I am kinda new to Django Rest Framework.
I have a views.py that looks something like this:
class MyAPIView(APIView):
""" My API """
def get(self, request, path):
""" Handles GET calls """
def post(self, request, path):
""" Handles POST calls """
And I have a util class in my package like so:
class MyUtilClass:
""" Helps out with stuff """
def some_method(self, path):
print('I will now do things to the path: ', path)
Now, I would like to inject an instance of some other class that does some task that it's supposed to into my view. Something like this:
class MyAPIView(APIView):
""" My API """
_some_util_instance = None # How to inject this?
def __init__(self, util_instance):
self._some_util_instance = util_instance # Is this the right way?
def get(self, request, path):
""" Handles GET calls """
self._some_util_instance.some_method(path) # This is why I want this object injected.
def post(self, request, path):
""" Handles POST calls """
What is the best way to inject such an instance into my views class?
I could not find much about this in the documentation. I am familiar with using DI and IoC Containers. However, I am not sure how Django Rest Framework handles all of that.
class MyAPIView(APIView):
""" My API """
_some_util_instance = MyUtilClass()
Or
class MyAPIView(APIView):
""" My API """
def __init__(self, *args, **kwargs):
self._some_util_instance = MyUtilClass()
super().__init__(self, *args, **kwargs)
Or
MyAPIView.as_view(
_some_util_instance=MyUtilClass()
)
class MyAPIView(APIView):
""" My API """
_some_util_instance = None
Or
don't use a class as a container for your utility functions, just define them as module-level functions. This is my preferred approach.
Or
Use static/class methods
class MyUtilClass:
""" Helps out with stuff """
#classmethod
def some_method(cls, path):
print('I will now do things to the path: ', path)
Then you can simply call MyUtilClass.some_method(path) in the view without creating an instance of MyUtilityClass
I'm building a rate-limiting decorator in flask using redis stores that will recognize different limits on different endpoints. (I realize there are a number of rate-limiting decorators out there, but my use case is different enough that it made sense to roll my own.)
Basically the issue I'm having is ensuring that the keys I store in redis are class-specific. I'm using the blueprint pattern in flask, which basically works like this:
class SomeEndpoint(MethodView):
def get(self):
# Respond to get request
def post(self):
# Respond to post request
The issue here is that I want to be able to rate limit the post method of these classes without adding any additional naming conventions. In my mind the best way to do this would be something like this:
class SomeEndpoint(MethodView):
#RateLimit # Access SomeEndpoint class name
def post(self):
# Some response
but within the decorator, only the post function is in scope. How would I get back to the SomeEndpoint class given the post function? This is the basic layout of the decorator. That might be confusing, so here's a more concrete example of the decorator.
class RateLimit(object):
"""
The base decorator for app-specific rate-limiting.
"""
def __call__(self, f):
def endpoint(*args, **kwargs):
print class_backtrack(f) # Should print SomeEnpoint
return f(*args, **kwargs)
return endpoint
basically looking for what that class_backtrack function looks like. I've looked through the inspect module, but I haven't found anything that seems to accomplish this.
You can decorate the entire class instead of just the methods:
def wrap(Class, method):
def wrapper(self, *args, **kwargs):
print Class
return method(self, *args, **kwargs)
return method.__class__(wrapper, None, Class)
def rate_limit(*methods):
def decorator(Class):
for method_name in methods:
method = getattr(Class, method_name)
setattr(Class, method_name, wrap(Class, method))
return Class
return decorator
#rate_limit('post')
class SomeEndpoint(object):
def post(self):
pass
class Subclass(SomeEndpoint):
pass
a = Subclass()
a.post()
# prints <class 'SomeEndpoint'>
I wanted to make it easier to register callbacks using decorators when designing a library, but the problem is that they both use the same instance of the Consumer.
I am trying to allow both these examples to co-exist in the same project.
class SimpleConsumer(Consumer):
#Consumer.register_callback
def callback(self, body)
print body
class AdvancedConsumer(Consumer):
#Consumer.register_callback
def callback(self, body)
print body
a = AdvancedConsumer()
s = SimpleConsumer()
What happens here is that the callback implementation of AdvancedConsumer will override the one of the SimpleConsumer, as it is defined last.
The implementation of the decorator class is pretty simple.
class Consumer(object):
def start_consumer(self):
self.consuming_messages(callback=self._callback)
#classmethod
def register_callback(cls, function):
def callback_function(cls, body):
function(cls, body)
cls._callback = callback_function
return callback_function
I am very happy with the implementation, but as there is a possibility that someone will register a second callback I would like to ensure that it won't be a problem in the future. So, does anyone have a suggestion on how to implement this in a way that is not static?
The implementation shown here is obviously simplified, and as a precaution I have something like this in the code.
if cls._callback:
raise RuntimeError('_callback method already defined')
You can do it with a class decorator:
def register_callback(name):
def decorator(cls):
cls._callback = getattr(cls, name)
return cls
return decorator
#register_callback('my_func')
class SimpleConsumer(Consumer):
def my_func(self, body):
print body
If you want to decorate a method, you will get only a function in it so you cannot access any information about the class that the method is contained in.
But if only one callback should be available per class why just not call it _callback?
class SimpleConsumer(Consumer):
def _callback(self, body):
print body
Or do something like:
class SimpleConsumer(Consumer):
def my_func(self, body):
print body
_callback = my_func
?
I want to use python-twitter, but extend the Status class to add a few new methods and attributes. What's the pythonic way to do this?
At the moment, I have functions which add attributes and new functionality to a Status, e.g.
process_status(status):
status.datetime = ...
status.phrase = ...
prettyprint_status(status):
# do something...
Naturally, I'd just like to add the extra methods to the Status constructor. I found a stackoverflow question discussing this which proposed making a new module, ext-twitter, which contains new implementations of each class, like follows:
# ext_twitter.py
import twitter
class Api(twitter.Api):
pass
class Status(twitter.Status):
def __init__(self, *args):
twitter.Status.__init__(self, *args)
self.args = args
self.time = parseTime(self.created_at)
self.phrase = ...
def prettyprint(self):
# something
However, this doesn't work since the Status classes are generated by the Twitter API object, and here ext-twitter.Api() calls python-twitter.Api() which has no reference to my extended Status class.
Any way to add my functionality to the python-twitter module without forking it and making my own version?
Try this:
# patch_twitter.py
import twitter
TwitterStatus = twitter.Status
class Status(TwitterStatus):
def __init__(self, *args, **kwargs):
TwitterStatus.__init__(self, *args, **kwargs)
self.args = args
self.time = parseTime(self.created_at)
self.phrase = ...
def prettyprint(self):
# something
twitter.Status = Status
# use api
This should work, at least for some values of "work". If there's anything else that captures a reference to the class object originally stored in twitter.Status, then those references won't be updated. That doesn't happen too often, but it could be a source of subtle bugs.
You'll need to import this immediately after importing twitter.py and before doing anything else.
Instead of using inheritance, you can use composition to add functionality to the Status object:
# ext_twitter.py
import twitter
class Api(twitter.Api):
def method_that_returns_status(self, *args, **kwargs):
status = super(Api, self).methot_that_returns_status(*args, **kwargs)
# wrap the original status with your custom status
return Status(status)
class Status(object):
def __init__(self, status):
self._internal = status
def __getattr__(self, attr):
return getattr(self._internal, attr)
def __setattr__(self, attr, value):
if attr == '_internal':
super(Status, self).__setattr__(attr, value)
else:
setattr(self._internal, attr, value)
def prettyprint(self):
# something
Is there a way to internally pass on the handling of a request from one RequestHandler subclass to another? Basically, what I would like to do is, from the get method of a RequestHandler (well, a subclass of RequestHandler), dispatch the task of handling the request to another handler (subclass of RequestHandler), whose name is determined by a value fetched from the datastore (I'm using GAE, but that is irrelevant to this problem). The code would look something like this:
class Dispatcher(RequestHandler):
def get_handler(some_id):
handler_name = get_handler_name(some_id) # fetches from datastore/etc.
return getattr(my_module, handler_name)
def get(self, some_id, *args, **kwargs):
handler = get_handler(some_id) # e.g., handler could be a HandlerA
# Not a real function, just to describe what to do:
# invokes get method of HandlerA (if handler == HandlerA)
dispatch_to_handler(handler, self, *args, **kwargs)
def post(self, some_id):
handler = get_handler(some_id)
dispatch_to_handler(....) # dispatches to post method of the handler
class HandlerA(RequestHandler):
def get(self, *args, **kwargs):
do_stuff()
def post(...):
do_post_stuff()
The big issue is that I need to somehow pass self and the positional and keyword arguments on to the other handler (HandlerA in this example), as self contains the request, response, session, authentication, and other data, which HandlerA (or whatever the handler may be) needs in order to process the request.
Try it this way:
def get(self, some_id, *args, **kwargs)
handler_cls = get_handler(some_id)
handler = handler_cls(self.request, self.response)
return handler.dispatch()