2010-03-20 15 views
5

Me estoy moviendo de un fondo de PHP en el desarrollo de Django a través de python, sobre todo por el bien de abordar un MVC (o MVT) que creo que tiene más sentido, aunque en este patrón Empecé a notar un montón de código repetido en mis puntos de vista.Django - Consejos para evitar la repetición de código en las vistas

Por ejemplo, cuando estoy conectado, tengo información sobre el usuario que me gustaría que aparezca en cada página, aunque cuando uso render_to_response y en cada vista es obligatorio, tengo que tomar la información y pasarla a la función render_to_response .

Me pregunto cuál sería la forma más eficiente de reducir el código duplicado que, en esencia, se requeriría en todas las vistas en una aplicación en particular.

Gracias de antemano.

Respuesta

4

Personalmente, soy un gran admirador de los decoradores, que son una característica de Python que no es específica de Django. Los decoradores son el azúcar sintáctico perfecto además de las funciones de orden superior, y son especialmente útiles para reducir las repeticiones en las vistas: puede definir rápidamente una función de envoltura generalizada, en la que puede poner el código repetitivo para facilitar su reutilización y conveniente. detener la refactorización.

Probablemente sea más fácil mostrarle que explicar cómo funcionan. He aquí un ejemplo de vista simplificada:

def listpage(request): 
    return HttpResponse(render_to_string("itemlist.html", { 
     "items": Item.objects.filter(visible=True).order_by("-modifydate") 
    })) 

def itemlist_tags(request, tags): 
    return HttpResponse(render_to_string("itemlist.html", { 
     "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"), 
    })) 

... pero luego dijo que quería que estas páginas requieren que el usuario ingrese Es posible agregar el código de inicio de sesión de este modo:.

def listpage(request): 
    if not request.user.is_authenticated(): 
     return f(request, *args, **kwargs) 
    else: 
     return HttpResponse(render_to_string("itemlist.html", { 
      "items": Item.objects.filter(visible=True).order_by("-modifydate") 
     })) 

def itemlist_tags(request, tags): 
    if not request.user.is_authenticated(): 
     return f(request, *args, **kwargs) 
    else: 
     return HttpResponse(render_to_string("itemlist.html", { 
      "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"), 
     })) 

.. .que está comenzando a ser notablemente más grande y repetitivo, incluso para un ejemplo artificial. Usted puede hacer sus funciones delgada de nuevo con decoradores, así:

del decorador decorador de importación

@decorator 
def loginrequired(f, request, *args, **kwargs): 
    if request.user.is_authenticated(): 
     return f(request, *args, **kwargs) 
    else: 
     return HttpResponseRedirect("/") 

@loginrequired 
def listpage(request): 
    return HttpResponse(render_to_string("itemlist.html", { 
     "items": Item.objects.filter(visible=True).order_by("-modifydate") 
    })) 

    @loginrequired 
def itemlist_tags(request, tags): 
    return HttpResponse(render_to_string("itemlist.html", { 
     "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"), 
    })) 

@loginrequired 
def another_such_function(request): 
    (...) 

@loginrequired 
def and_again(request): 
    (...) 

lo que sucede es la función decoradora se ejecuta en el momento de la definición de la función. La 'f' en mi ejemplo es un objeto que representa la función a la que se aplica el decorador, que puede manipular de manera interminable.

Esto requiere el decorator library, que es gratis en PyPI, como lo son muchos buenos bocados de pitón, usted encontrará.

No necesita esta biblioteca para escribir funciones de decorador, pero es útil, especialmente al principio. Pueden hacer mucho más: cualquier llamante puede ser un decorador; puede decorar métodos de clase e interceptar la variable self; decoradores pueden ser encadenados, así:

@second 
@first 
def originalfunction(*args): 
    (...) 

Voy a dejar la exploración de lo que puede hacer con tales manpipulation sencilla función de orden superior para usted, esta noción debe abrir el apetito. También tengo muchos más ejemplos, para ti o cualquier otro curioso nuevo aficionado de Python. Buena suerte.

+1

Por cierto, la función 'etiquetada()' en la segunda vista falsa no es un error tipográfico; es una interfaz simplificada que escribí en la aplicación django-tagging, también en el nombre de la reducción de etiquetas, que los curiosos encontrarán aquí: http://www.djangosnippets.org/snippets/1942/ – fish2000

+0

Muy útil, gracias, decoradores parece tener muchos usos adicionales para mí. – neopickaze

5

Encapsula el código común en una función y lo llama desde diferentes vistas. Suena trivial, pero es la solución para el 99% de esas necesidades.

Para una respuesta más específica, tendrá que mostrar un ejemplo más concreto del código que desea ejecutar.

5

Existen dos formas principales de abstraer contenido común.

Context processors son los mejores para pasar pedazos de datos que usted sabe que necesitará en cada vista.

Template tags - especialmente las etiquetas de inclusión - son útiles para representar áreas separadas de la página que serán las mismas en varias plantillas.

3

Además, no se olvide de generic views! En el 90% de los casos, puede ajustar object_list o object_detail y ahorrarse un poco de código.

Cuestiones relacionadas