python - tutorial - href django




Vistas de clase en Django (6)

Django view apunta a una función, que puede ser un problema si desea cambiar solo un poco de funcionalidad. Sí, podría tener millones de argumentos de palabras clave e incluso más si las declaraciones en la función, pero estaba pensando más en un enfoque orientado a objetos.

Por ejemplo, tengo una página que muestra un usuario. Esta página es muy similar a la página que muestra un grupo, pero aún no es tan similar a usar otro modelo de datos. El grupo también tiene miembros, etc.

Una forma sería apuntar vistas a métodos de clase y luego extender esa clase. ¿Alguien ha intentado este enfoque o tiene alguna otra idea?


A menos que desee hacer algo un poco complejo, utilizar las vistas genéricas es el camino a seguir. Son mucho más potentes de lo que su nombre lo indica, y si solo está mostrando datos de modelo, las vistas genéricas harán el trabajo.


He creado y usado mis propias clases de vista genéricas, definiendo __call__ para que una instancia de la clase sea invocable. Me gusta mucho; mientras que las vistas genéricas de Django permiten cierta personalización a través de argumentos de palabras clave, las vistas genéricas de OO (si su comportamiento se divide en varios métodos separados) pueden tener una personalización mucho más detallada a través de la subclasificación, lo que me permite repetirme mucho menos. (Me canso de reescribir la misma lógica de vista de creación / actualización cada vez que necesito modificar algo que las vistas genéricas de Django no permiten).

He publicado un código en djangosnippets.org .

El único inconveniente real que veo es la proliferación de llamadas a métodos internos, que pueden afectar el rendimiento de alguna manera. No creo que esto sea una gran preocupación; Es raro que la ejecución del código de Python sea su cuello de botella de rendimiento en una aplicación web.

ACTUALIZACIÓN : las propias vistas genéricas de Django ahora están basadas en clases.

ACTUALIZACIÓN : FWIW, he cambiado mi opinión sobre las opiniones basadas en la clase desde que se escribió esta respuesta. Después de haberlos usado extensamente en un par de proyectos, siento que tienden a generar código que es satisfactoriamente SECO para escribir, pero muy difícil de leer y mantener más tarde, porque la funcionalidad se extiende por tantos lugares diferentes y las subclases son muy dependientes en cada detalle de implementación de las superclases y mixins. Ahora siento que TemplateResponse y los decoradores de vistas son una mejor respuesta para descomponer el código de vista.


Me parece que estás tratando de combinar cosas que no deberían combinarse. Si necesita hacer un procesamiento diferente en su vista dependiendo de si es un objeto de Usuario o Grupo que está tratando de ver, entonces debe usar dos funciones de vista diferentes.

Por otro lado, puede haber expresiones idiomáticas comunes que desee extraer de sus vistas de tipo object_detail ... ¿tal vez podría usar un decorador o simplemente funciones auxiliares?

-Dan


Necesitaba usar vistas basadas en clases, pero quería poder usar el nombre completo de la clase en mi URLconf sin tener que crear instancias de la clase de vista antes de usarla. Lo que me ayudó fue una metaclase sorprendentemente simple:

class CallableViewClass(type):
    def __call__(cls, *args, **kwargs):
        if args and isinstance(args[0], HttpRequest):
            instance = super(CallableViewClass, cls).__call__()
            return instance.__call__(*args, **kwargs)
        else:
            instance = super(CallableViewClass, cls).__call__(*args, **kwargs)
            return instance


class View(object):
    __metaclass__ = CallableViewClass

    def __call__(self, request, *args, **kwargs):
        if hasattr(self, request.method):
            handler = getattr(self, request.method)
            if hasattr(handler, '__call__'):
                return handler(request, *args, **kwargs)
        return HttpResponseBadRequest('Method Not Allowed', status=405)

Ahora puedo crear instancias de clases de vista y usar las instancias como funciones de vista, O simplemente puedo apuntar mi URLconf a mi clase y hacer que la metaclase instancia (y llame) la clase de vista por mí. Esto funciona comprobando el primer argumento de __call__ : si se trata de una solicitud HttpRequest , debe ser una solicitud HTTP real porque sería absurdo intentar instanciar una clase de vista con una instancia HttpRequest .

class MyView(View):
    def __init__(self, arg=None):
        self.arg = arg
    def GET(request):
        return HttpResponse(self.arg or 'no args provided')

@login_required
class MyOtherView(View):
    def POST(request):
        pass

# And all the following work as expected.
urlpatterns = patterns(''
    url(r'^myview1$', 'myapp.views.MyView', name='myview1'),
    url(r'^myview2$', myapp.views.MyView, name='myview2'),
    url(r'^myview3$', myapp.views.MyView('foobar'), name='myview3'),
    url(r'^myotherview$', 'myapp.views.MyOtherView', name='otherview'),
)

(Publiqué un fragmento para esto en http://djangosnippets.org/snippets/2041/ )


Si desea compartir una funcionalidad común entre páginas, le sugiero que busque etiquetas personalizadas. Son bastante fáciles de crear y son muy potentes.

Además, las plantillas pueden extenderse desde otras plantillas . Esto le permite tener una plantilla base para configurar el diseño de la página y compartirla entre otras plantillas que completan los espacios en blanco. Puede anidar plantillas a cualquier profundidad; lo que le permite especificar el diseño en grupos separados de páginas relacionadas en un solo lugar.


Si simplemente está mostrando datos de modelos, ¿por qué no usar las Vistas genéricas de Django ? Están diseñados para que pueda mostrar fácilmente los datos de un modelo sin tener que escribir su propia vista y cosas sobre el mapeo de los parámetros de URL a las vistas, la obtención de datos, el manejo de casos extremos, la salida de representación, etc.





oop