[pyar] Puedo usar decoradores para esto?

John Rowland Lenton john.lenton en canonical.com
Jue Jun 10 21:59:21 ART 2010


On Thu, Jun 10, 2010 at 05:55:35PM -0300, Hystrix wrote:
> Buenas gente, que tal?
> 
> Estoy haciendo un app en Django y mirando las vistas que estaba por
> escribir me di cuenta que estoy repitiendo una estructura para todas.
> Sin saber mucho del tema me pregunto, podre usar un decorador para
> eliminar la repeticion?
> 
> Las vistas comparten esta estructura basica:
> 
> def vista_a(request, id):
>   data = {'area': 'i'}
>   data['obj'] = get_object_or_404(modelo, pk=id)
>   #cosas propias de la vista
>   #usa cosas de data y agrega cosas a data
>   #tambien usa cosas de request
>   #aca se define el template
>   return render_to_response(template, data)
> 
> 
> Mi idea inicial era hacer un decorador que se ocupe de crear "data" y
> despues devolver la respuesta http con render_to_response.
> Pero no se como hacer para pasar los datos entre el decorador y la
> funcion decorada.
> 
> Tampoco quiero meterme en demasiadas complicaciones porque no se
> justifica en este caso pero tal vez hay una forma simple y elegante de
> evitar la repeticion en todas las vistas. Hay?

lo que estás viendo es que tenés muchas funciones de la pinta

    def f(x):
      y = f1(x)
      z = f2(x, y)
      return f3(x, y, z)

donde f1 y f3 son siempre las mismas, y f2 es la "carne" de
f. Entonces un decorador de la pinta

    def f1f3(f):
      @wraps(f)
      def gf(x):
        y = f1(x)
        z = f(x, y)
        return f3(x, y, z)
      return g

entonces decorás a f2 con f1f3 y te queda la f que vos
querías. Refácil :)

Ahora, en tu caso, muchas veces lo que pasa es que el template no
cambia para una vista dada, y que no necesitás más el id una vez que
ya tenés el objeto. Entonces podés aprovechar estas dos cosas y hacer

    def decorar(template):
      # esto es una fábrica de decoradores, en realidad
      def decorador(f):
        @wraps(f)
        def g(request, id):
          obj = get_object_or_404(modelo, pk=id)
          data = f(request, obj)
          data['obj'] = obj
          # por las dudas f alguna vez 'pisara' el area original
          data.setdefault('area', 'i')
          return render_to_response(template, data)
        return g
      return decorador

y esto lo usarías así:

    @decorar('nombre_del_template.html')
    def vista_a(request, obj):
      #aca se define data
      #cosas propias de la vista
      #usa cosas de data y agrega cosas a data
      #tambien usa cosas de request
      return data

y listo.
------------ próxima parte ------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20100610/55a36cbf/attachment.sig>


More information about the pyar mailing list