Aquí podría ser tu PUBLICIDAD


Vistas de clase en Django

votos
48

La vista Django apunta a una función, lo que puede ser un problema si solo quieres cambiar un poco de funcionalidad. Sí, podría tener millones de argumentos de palabras clave y aún más si hay enunciados 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 simplemente 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 probado este enfoque o tiene alguna otra idea?

Publicado el 03/08/2008 a las 16:55
fuente por usuario Seb
En otros idiomas...        العربية       

9 respuestas

votos
41

Creé y usé 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 OO (si su comportamiento se divide en varios métodos separados) pueden tener una personalización mucho más fina mediante subclases, lo que me permite repetir mucho menos. (Me cansé de volver a escribir la misma lógica de creación / actualización de vista en cualquier momento que necesite 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 un poco el rendimiento. No creo que esto sea una gran preocupación; es raro que la ejecución del código 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 vistas basadas en clases desde que se escribió esta respuesta. Después de haberlos utilizado extensamente en un par de proyectos, creo que tienden a generar un código que es satisfactorio DRY para escribir, pero muy difícil de leer y mantener más tarde, porque la funcionalidad se distribuye en tantos lugares diferentes, y las subclases son muy dependientes. en cada detalle de implementación de las superclases y mixinas. Ahora siento que TemplateResponse y view decorators es una mejor respuesta para descomponer el código de vista.

Respondida el 29/08/2008 a las 05:29
fuente por usuario Carl Meyer


Aquí podría ser tu PUBLICIDAD


votos
13

Necesitaba usar puntos de vista basados ​​en la clase, pero quería ser capaz de utilizar el nombre completo de la clase en mi URLconf sin tener siempre que una instancia de la clase de vista antes de usarlo. 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)

Puedo ahora ambos instanciar clases de vista y utilizar las instancias como funciones de vista, o simplemente puedo señalar mi URLconf a mi clase y tienen la instantiate metaclase (y llamar) la clase de vista para mí. Esto funciona mediante la comprobación de que el primer argumento __call__- si es una HttpRequest, debe ser una petición HTTP real porque sería absurdo attept para crear instancias de una clase de vista con un HttpRequestejemplo.

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'),
)

(He publicado un fragmento de este a http://djangosnippets.org/snippets/2041/ )

Respondida el 27/05/2010 a las 02:02
fuente por usuario Erik Allik

votos
9

Si simplemente muestra datos de modelos, ¿por qué no utiliza 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 la asignación de parámetros de URL a las vistas, la obtención de datos, el manejo de casos límite, la representación de resultados, etc.

Respondida el 07/08/2008 a las 11:44
fuente por usuario rossp

votos
3

Siempre puede crear una clase, anular la __call__función y luego señalar el archivo URL a una instancia de la clase. Puede echar un vistazo a la clase de FormWizard para ver cómo se hace esto.

Respondida el 26/08/2008 a las 12:38
fuente por usuario dguaraglia

votos
2

A menos que quiera hacer algo un poco complejo, usar las vistas genéricas es el camino a seguir. Son mucho más poderosos de lo que su nombre lo indica, y si solo muestra los datos del modelo, las vistas genéricas harán el trabajo.

Respondida el 11/08/2008 a las 11:59
fuente por usuario Harley Holcombe

votos
2

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 se trata de un objeto de Usuario o Grupo que está tratando de observar, entonces debe usar dos funciones de vista diferentes.

Por otro lado, puede haber expresiones idiomáticas comunes que desearía extraer de sus vistas tipo de objeto_detallado ... ¿quizás podría usar un decorador o simplemente funciones auxiliares?

-Dan

Respondida el 03/08/2008 a las 06:40
fuente por usuario Dan

votos
1

Puede utilizar las Vistas Django genéricos. Usted puede lograr fácilmente funcionalidad deseada exhaustivas Django genéricos Vistas

Respondida el 08/10/2014 a las 06:53
fuente por usuario Varun Chadha

votos
1

Generalmente, las vistas genéricas serán el camino a seguir, pero en última instancia, usted es libre de manejar las URL como desee. FormWizard hace cosas en una forma basada en clases, al igual que algunas aplicaciones para API RESTful.

Básicamente, con una URL, se le da un conjunto de variables y un lugar para proporcionar una llamada, lo que usted puede proporcionar depende de usted, la forma estándar es proporcionar una función, pero en última instancia, Django no impone restricciones sobre lo que usted hace.

Estoy de acuerdo en que unos pocos ejemplos más de cómo hacer esto serían buenos, sin embargo, FormWizard es probablemente el lugar para comenzar.

Respondida el 23/09/2008 a las 08:05
fuente por usuario Andrew Ingram

votos
1

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 poderosos.

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; permitiéndole especificar el diseño en grupos separados de páginas relacionadas en un solo lugar.

Respondida el 26/08/2008 a las 12:30
fuente por usuario Andrew Wilkinson