Login

PK->objects in view signature

Author:
AdamKG
Posted:
March 29, 2008
Language:
Python
Version:
.96
Tags:
decorator
Score:
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 argument (excluding request.)

@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

More like this

  1. Other approach of making middleware (by decorators) by diverman 4 years, 2 months ago
  2. Render Decorator by dahool 5 years, 8 months ago
  3. render_to by asolovyov 6 years, 11 months ago
  4. Allow separation of GET and POST implementations by agore 2 years, 11 months ago
  5. Format transition middleware by limodou 8 years, 2 months ago

Comments

Please login first before commenting.