February 4, 2008.
Just a quick blog entry about something thats pretty simple, but can be a nice way to avoid rewriting code: taking advantage of optional parameters in Django views.
Recently when I was writing the LifeFlow Editor, I found myself wanting to be able to render pieces of text by sending them via ajax to the backend and then displaying that newly rendered text. There were two situations where I wanted to do this: sometimes I wanted to render text posted to the view, and sometimes I wanted to render text from a specific model instance, whose class and primary key were being posted to the view.
To do this I write these views:
from lifeflow.models import * urlpatterns = patterns('lifeflow.editor.views', (r'^render/$', 'render'), (r'^render/(?P<model>\w+)/(?P<id>\d+)/$', 'render'), )
In the first I am passing two arguments to render, and in the second I am zero arguments to render, but they are definitely the same view, how does that work?
Pretty easily it turns out:
@login_required def render(request, model=None, id=None): if id is None: txt = dbc_markup(request.POST['txt']) else: if model == u"draft": obj = Draft.objects.get(pk=id) elif model == u"entry": obj = Entry.objects.get(pk=id) if obj.use_markdown: txt = dbc_markup(obj.body, obj) else: txt = obj.body return HttpResponse(txt)
If I don't get an ID then I know I want to check the POST for text to render, otherwise I use the primary key and model to render the Draft or Entry instance.
(The login_required decorator is used here to prevent unauthorized users from accessing this view. Also the content validation is quite sloppy, but this view can't cause any damage to data, only display it in places it perhaps shouldn't be, but since access is restricted to those who could access the data anyway, this isn't a big concern for me.)
Just a simple technique that pops up occasionally and can help keep your code clean and unrepeated.