-
-
Save sneeu/2768694 to your computer and use it in GitHub Desktop.
def beta_access(request): | |
if request.method == 'POST': | |
form = BetaCodeForm(request.POST) | |
# form validation handles checking for the beta code | |
if form.is_valid(): | |
request.session['has_beta_access'] = True | |
return redirect('register') | |
else: | |
form = BetaCodeForm(request.POST) | |
return TemplateResponse(request, 'beta_access.html', context={'form': form}) | |
def beta_access_required(view): | |
def f(request, *args, **kwargs): | |
if request.session.get('has_beta_access', None) != True: | |
return redirect('beta_access') | |
return view(request, *args, **kwargs) | |
return f |
@pyrat: in the definition, args (with one *) is a tuple of positional arguments, kwargs (with two *s) is a dictionary of named arguments. In a function call, they can be used to expand a tuple (or list), and/or a dict of paramters into arguments.
For example:
def something(a, b, c):
# Do something
Can be called:
something(1, 2, 3)
something(*[1, 2, 3])
something(**{'a': 1, 'b': 2, 'c': 3})
Why you want to do this is another lesson ;)
@pyrat - ** means the argument is a dictionary of any provided named parameters. With a single *, the argument is a list of indexed parameters.
def my_func(*args, **kwargs):
print args, kwargs
my_func(100, 300, name='Bob', age=12)
would print:
[100, 300] {'name': 'Bob', 'age'=12}
Dammit, sneeu beat me with a better-formatted answer ;)
@bedmondmark only just—updated your comment to have better formatting too.
Thanks. Seems like a nice feature.. the alternative being passing a hash / object to a function instead for named parameters.
So can I have the lesson: Why would you want to do this?
@pyrat there are quite a few reasons, Jinja2 uses the keyword arguments to define the context in a template.
In the example above, we’re defining a decorator, which is used:
someview = beta_access_required(someview)
The original someview
function is wrapped by the beta_access_required
decorator, which in the example replaces it with f
(which has a closure over view
, so the original view
can be called from within).
But the beta_access_required
function doesn’t really care about the arguments, so it can pass them straight through, image having to write a different beta_access_required
for every view function signature.
Django’s user_passes_test
decorator (which is what login_required
is) is similar.
Python also has the syntactic sugar:
@beta_access_required
def someview(request, some, arguments):
pass
Which is the same as the above.
@pyrat additionally, in Django if you wanted to do something before saving a model, you overwrite the save
method, and eventually call super
, generally you’re not bothered about what save
is called with, so you’d use *args
, and **kwargs
in that instance too.
An example:
class TimestampedModel(models.Model):
last_updated = models.DatetimeField(blank=True, null=True)
def save(self, *args, **kwargs):
# Not too bothered about what args are used, just throw them up the inheritance tree.
self.last_updated = datetime.datetime.utcnow()
super(TimestampedModel, self).save(*args, **kwargs)
Nice, thanks for the rundown. Hopefully I will find an excuse to write some Python in the near future.
Python newbie question: What does **kwargs with the 2 * mean as opposed to one?