poniedziałek, 11 lutego 2008

render_to_response

Zacznę od czegoś związanego z optymalizacją. Optymalizacja to ostatni etap rozwoju aplikacji, ale kto powiedział że zaczynamy :).

Standardowo używa się funkcji render_to_response. Jest ona prosta i szybka w użyciu. Jednak nie jest ona optymalna. Za każdym razem pliki z szablonami są ładowane z dysku i parsowane. Aby najpierw załadować plik z dysku i go sparsować wystarczy napisać:

from django.template import loader
temp = loader.get_template(template)

Po tym możemy mamy już wszystko przygotowane i wystarczy wywoływać funkcję render:

temp.render(context)

Teraz jeszcze tylko zapisać wszystkie szablony do jakiejś tablicy i gotowe.

Moja funkcja z cachem wygląda tak:

templates = {}

def django_template_to_string( request, variables, template ):
    if not DEVEL:
        temp = templates.get( template )
        if temp is None:
            temp = loader.get_template(template)
            templates[template] = temp
    else:
        temp = loader.get_template(template)

    c = RequestContext(request)
    c.update(variables)
    return temp.render(c)]

Należy pamiętać, że teraz szablony są trzymane w pamięci, co jest niewygodne podczas rozwijania aplikacji, ponieważ po każdej zmianie w html-u trzeba restartować serwer Django. Dlatego też dla danego przykładu należy ustawić zmienną DEVEL, aby było tak jak poprzednio.

Dla ułatwienia pracy warto jest użyć dekorator, aby wszystko się działo automatycznie:

decorator_with_args = lambda decorator: lambda *args, **kwargs: lambda func: decorator(func, *args, **kwargs )

@decorator_with_args
def django_template(func, template=None):
    def wrapper(request,*args,**kwargs):
        variables = func(request, *args, **kwargs )
        string = django_template_to_string( request, variables, template )
        return HttpResponse( string )

    wrapper.__name__ = func.__name__
    wrapper.__dict__ = func.__dict__
    wrapper.__doc__ = func.__doc__
    return wrapper</code>
Teraz użycie jest prostsze niż domyślnie:
@django_template("moja_strona.html")
def master_home(request):
    variables = { 'title'   : "Hello World!" }
    return variables

Żadnego render_to_response. Żadnego martwienia się, aby szybko chodziło.

Ok, zobaczmy jakie jest przyśpieszenie dla dość skomplikowanej strony:

render_to_response: Time per request:       223ms
django_template.py: Time per request:       101ms

Jak widać jest to bardzo znacząca różnica. Pełny kod źródłowy: django_template.py

1 komentarz:

forgems pisze...

Strasznie długie te czasy renderowania :) na p200 robiliscie te testy ? Z moich obserwacji nie wynika takie duze przyspieszenie ( moze 30-40%).