Skip to content

Instantly share code, notes, and snippets.

@sneeu
Created May 22, 2012 12:15
Show Gist options
  • Save sneeu/2768694 to your computer and use it in GitHub Desktop.
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
@sneeu
Copy link
Author

sneeu commented May 22, 2012

@bedmondmark only just—updated your comment to have better formatting too.

@pyrat
Copy link

pyrat commented May 23, 2012

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?

@sneeu
Copy link
Author

sneeu commented May 23, 2012

@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.

@sneeu
Copy link
Author

sneeu commented May 23, 2012

@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)

@pyrat
Copy link

pyrat commented May 24, 2012

Nice, thanks for the rundown. Hopefully I will find an excuse to write some Python in the near future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment