Pregunta

Django La vista apunta a una función, lo 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 declaraciones if 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 como para usar simplemente 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?

¿Fue útil?

Solución

He creado y usado mis propias clases de vista genéricas, definiendo __call__ entonces una instancia de la clase es 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 subclases, lo que me permite repetirme mucho menos.(Me canso de reescribir la misma lógica de creación/actualización de vista 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, lo que puede afectar un poco el rendimiento.No creo que esto sea una gran preocupación;Es raro que la ejecución de código Python sea un cuello de botella en el rendimiento de una aplicación web.

ACTUALIZAR:El propio Django vistas genéricas ahora se basan en clases.

ACTUALIZAR:FWIW, cambié mi opinión sobre las opiniones basadas en clases desde que se escribió esta respuesta.Después de haberlos usado extensamente en un par de proyectos, siento que tienden a conducir a un código que es satisfactoriamente SECO de escribir, pero muy difícil de leer y mantener más adelante, porque la funcionalidad se distribuye en muchos lugares diferentes y las subclases son muy dependientes. en cada detalle de implementación de las superclases y mixins.ahora siento que Respuesta de plantilla y los decoradores de vistas son una mejor respuesta para descomponer el código de vista.

Otros consejos

Necesitaba usar vistas basadas en clases, pero quería poder usar el nombre completo de la clase en mi URLconf sin tener que crear siempre una instancia 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 cree una instancia (y llame) a la clase de vista por mí.Esto funciona comprobando el primer argumento para __call__ – si es un HttpRequest, debe ser una solicitud HTTP real porque no tendría sentido intentar crear una instancia de una clase de vista con un HttpRequest instancia.

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 de esto en http://djangosnippets.org/snippets/2041/)

Si simplemente está mostrando datos de modelos, ¿por qué no utilizar el Vistas genéricas de Django?Están diseñados para permitirle mostrar fácilmente datos de un modelo sin tener que escribir su propia vista y cosas sobre cómo asignar parámetros de URL a vistas, obtener datos, manejar casos extremos, renderizar resultados, etc.

Siempre puedes crear una clase, anular la __call__ función y luego apunte el archivo URL a una instancia de la clase.Puedes echarle un vistazo a Asistente de formularios clase para ver cómo se hace esto.

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

Por otro lado, puede haber modismos comunes que querrás extraer de tus vistas de tipo object_detail...¿Quizás podrías usar un decorador o simplemente funciones auxiliares?

-dan

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

Las vistas genéricas normalmente serán el camino a seguir, pero en última instancia eres libre de manejar las URL como quieras.FormWizard hace las cosas basado en clases, al igual que algunas aplicaciones para API RESTful.

Básicamente, con una URL se le proporciona un montón de variables y un lugar para proporcionar un invocable, lo invocable que proporcione depende completamente de usted (la forma estándar es proporcionar una función), pero en última instancia, Django no pone restricciones a lo que hace.

Estoy de acuerdo en que sería bueno tener algunos ejemplos más de cómo hacer esto, pero FormWizard es probablemente el lugar para comenzar.

Si desea compartir funciones comunes entre páginas, le sugiero que consulte las etiquetas personalizadas.son bastante fácil de crear, y son muy poderosos.

También, 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.

Puede utilizar las vistas genéricas de Django.Puede lograr fácilmente la funcionalidad deseada a través de las vistas genéricas de Django.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top