- January 26, 2011
- forms request mixin request.user
- 0 (after 0 ratings)
More a proof of concept than anything, this mixin addresses a perceived "shortcoming" of django forms: the inability to interact with the current request, and specifically the "current user".
class SomeForm(forms.Form, RequestFetchingMixin): # fields... def __init__(self, *args, **kwargs): if self.request: # interact with self.request? super(SomeForm, self).__init__(*args, **kwargs) if self.request: # more interaction def clean(self): if self.request: # blah blah self.request.user blah
- This reaches "into the past" to pull an existing HttpRequest object, regardless of what name it was bound to, into "the present".
- If multiple requests are found (what on earth are you doing??), the one bound to "request" (or the first one found, if that's not available) will be used.
- By default it goes up to 5 frames back before giving up, but that can obviously be changed if you think you need it.
- This won't work everywhere. self.request is guaranteed to be present, but may be None.
- Just because you have a self.request doesn't mean self.request.user will be a valid user. This is subject to all the rules that a regular view's request is subject to (because it is a regular view's request!)
- This isn't magic; it's just python.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
from django.http import HttpRequest import inspect class RequestFetchingMixin(object): def __new__(cls, *args, **kwargs): obj = object.__new__(cls, *args, **kwargs) f = inspect.currentframe() requests =  request = None backup_count = 0 while not requests and f.f_back is not None and backup_count < 5: f = f.f_back for var, val in f.f_locals.iteritems(): if isinstance(val, HttpRequest): requests.append((var, val)) backup_count += 1 if not requests: request = None elif len(requests) == 1: request = requests else: for var, val in requests: if var == 'request': request = val if request is None: request = requests obj.request = request return obj