- March 29, 2008
- 0 (after 0 ratings)
Let's suppose you have a view that fetches an object and renders a template with it.
def show_blog_post(request, post_id): post = Post.objects.get(pk=int(post_id)) return render_to_response("show_post.html", dict(post=post))
That's all well and good. This decorator just lets you move one statement into what is essentially a declaration at the top of the function: "this is a view, that gets passed a primary-key ID, which I want to get the Post object for."
@sigtransform([Post, int]) def show_blog_post(request, post): # post is actually the Post instance now! return render_to_response("show_post.html", dict(post=post))
If you want to leave an argument alone, pass None as that positional
@sigtransform(None, [MyModel, str]): def show_mymodel_stuff(request, leave_me_alone, model_obj): # ...etc...
Internally, this just calls get_object_or_404 with the pk kwarg, which means it's not limited to integer keys. However, Model.objects.get requires that the pk arg be of the correct type, hence why the arguments are 2-element lists or tuples: the first is the actual model, the second is what cleaner function to apply to the passed in argument.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
def sigtransform(*Models): import django from django.shortcuts import get_object_or_404 def _decorator(func): def _closure(request, *args, **kwargs): args = list(args) for ii, Model_and_cleaner in enumerate(Models): # None is passed to @sigtransform to indicate "leave # this argument alone" if Model_and_cleaner is None: pass else: Model, cleaner = Model_and_cleaner # pk arg needs correct datatype, hence cleaner func. args[ii] = get_object_or_404(Model, pk=cleaner(args[ii])) return func(request, *args, **kwargs) _closure.__name__ = func.__name__ _closure.__doc___ = func.__doc__ _closure.__module___ = func.__module__ return _closure return _decorator