Vistas de clase en Django -- python campo con django campo con views campo con oop camp Relacionados El problema

Class views in Django


55
vote

problema

Español

django Ver puntos a una función, lo que puede ser un problema si quieres cambiar solo un poco de funcionalidad. Sí, podría tener un millón de argumentos de palabras clave e incluso más si las declaraciones en la función, pero estaba pensando en más 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 señalar puntos de vista a los métodos de clase y luego extender esa clase. ¿Alguien ha probado este enfoque o tiene alguna otra idea?

Original en ingles

Django view points to a function, which can be a problem if you want to change only a bit of functionality. Yes, I could have million keyword arguments and even more if statements in the function, but I was thinking more of an object oriented approach.

For example, I have a page that displays a user. This page is very similar to page that displays a group, but it's still not so similar to just use another data model. Group also has members etc...

One way would be to point views to class methods and then extend that class. Has anyone tried this approach or has any other idea?

</div
           

Lista de respuestas

42
 
vote
vote
La mejor respuesta
 

He creado y utilizado mis propias clases de vista genérica, definiendo "Any CPU"7 por lo que se puede llamar una instancia de la clase. Me gusta mucho; Mientras que las vistas genéricas de Django permiten cierta personalización a través de los argumentos de la palabra clave, las vistas genéricas de OO (si su comportamiento se divide en una serie de métodos separados) puede tener una personalización mucho más fina a través de la subclasificación, lo que me permite repetirme mucho menos. (Me canso de volver a escribir la misma lógica de creación / actualización de la lógica en cualquier momento que necesite modificar algo que las vistas genéricas de Django no permiten,

He publicado algún código en djangosnippets.org .

El único inconveniente real que veo es la proliferación de llamadas de métodos internos, que pueden afectar el rendimiento un poco. 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.

update : Django es propio vistas genéricas ahora están basados ​​en la clase.

update : FWIW, he cambiado mi opinión sobre las vistas basadas en clase desde que esta respuesta fue escrita. Después de haberlos utilizado ampliamente en un par de proyectos, siento que tienden a conducir al código que está satisfactoriamente seco para escribir, pero muy difícil de leer y mantener más tarde, porque la funcionalidad se extiende a muchos lugares diferentes, y las subclases son tan dependientes. En cada detalle de implementación de las Superclases y Mixins. Ahora siento que templatireSponse y Ver decoradores es una mejor respuesta para descomponerse Ver código.

 

I've created and used my own generic view classes, defining __call__ so an instance of the class is callable. I really like it; while Django's generic views allow some customization through keyword arguments, OO generic views (if their behavior is split into a number of separate methods) can have much more fine-grained customization via subclassing, which lets me repeat myself a lot less. (I get tired of rewriting the same create/update view logic anytime I need to tweak something Django's generic views don't quite allow).

I've posted some code at djangosnippets.org.

The only real downside I see is the proliferation of internal method calls, which may impact performance somewhat. I don't think this is much of a concern; it's rare that Python code execution would be your performance bottleneck in a web app.

UPDATE: Django's own generic views are now class-based.

UPDATE: FWIW, I've changed my opinion on class-based views since this answer was written. After having used them extensively on a couple of projects, I feel they tend to lead to code that is satisfyingly DRY to write, but very hard to read and maintain later, because functionality is spread across so many different places, and subclasses are so dependent on every implementation detail of the superclasses and mixins. I now feel that TemplateResponse and view decorators is a better answer for decomposing view code.

</div
 
 
 
 
12
 
vote

Necesitaba usar las vistas basadas en clase, pero quería poder usar el nombre completo de la clase en mi URLCONF sin tener que siempre tener que instanciar la clase de vista antes de usarla. Lo que me ayudó fue un metaclasto 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 instanciar las clases de visualización y usar las instancias como Funciones de la vista, o simplemente puedo apuntar mi URLCONF a mi clase y tener la instancia de Metaclass (y llamar) la clase de vista para mí. Esto funciona revisando el primer argumento a __call__ - Si es un HttpRequest , debe ser una solicitud HTTP real porque sería una tontería para instanciar 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 para esto en http://djangosnippets.org/snippets/2041/)

 

I needed to use class based views, but I wanted to be able to use the full name of the class in my URLconf without always having to instantiate the view class before using it. What helped me was a surprisingly simple metaclass:

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) 

I can now both instantiate view classes and use the instances as view functions, OR I can simply point my URLconf to my class and have the metaclass instantiate (and call) the view class for me. This works by checking the first argument to __call__ – if it's a HttpRequest, it must be an actual HTTP request because it would be nonsense to attept to instantiate a view class with an HttpRequest instance.

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

(I posted a snippet for this at http://djangosnippets.org/snippets/2041/)

</div
 
 
10
 
vote

Si simplemente está mostrando datos de los modelos, por qué no usar el Django Vistas genéricas ? Están diseñados para permitirle fácil mostrar datos de un modelo sin tener que escribir su propia vista y cosas sobre el mapeo de parámetros de URL para las vistas, recuperar los datos, la manipulación de casos de borde, la salida de renderizado, etc.

 

If you're simply displaying data from models, why not use the Django Generic Views? They're designed to let you easy show data from a model without having to write your own view and stuff about mapping URL paramaters to views, fetching data, handling edge cases, rendering output, etc.

</div
 
 
3
 
vote

Siempre puede crear una clase, anular la función public static string ToTitleCaseInvariant(string targetString) { return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(targetString); } 5 y luego apunte el archivo URL a una instancia de la clase. Puede echar un vistazo a la formwizard clase para ver cómo se hace esto.

 

You can always create a class, override the __call__ function and then point the URL file to an instance of the class. You can take a look at the FormWizard class to see how this is done.

</div
 
 
 
 
2
 
vote

Me suena como si estuvieras tratando de combinar cosas que no deberían combinarse. Si necesita hacer un procesamiento diferente en su opinión, dependiendo de si es un objeto de usuario o grupo que está intentando mirar, debe usar dos funciones de vista diferentes.

Por otro lado, puede haber modismos comunes que desea extraer de sus vistas de tipo de objeto_detail ... ¡quizás pueda usar un decorador o simplemente funciones de ayuda?

-DAN

 

Sounds to me like you're trying to combine things that shouldn't be combined. If you need to do different processing in your view depending on if it's a User or Group object you're trying to look at then you should use two different view functions.

On the other hand there can be common idioms you'd want to extract out of your object_detail type views... perhaps you could use a decorator or just helper functions?

-Dan

</div
 
 
2
 
vote

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

 

Unless you want to do something a little complex, using the generic views are the way to go. They are far more powerful than their name implies, and if you are just displaying model data generic views will do the job.

</div
 
 
1
 
vote

Las vistas genéricas generalmente serán la forma de ir, pero en última instancia, usted es libre de manejar las URL sin embargo, usted quiere. FormWizard hace las cosas de una manera basada en la clase, al igual que algunas aplicaciones para API APIES RESTUPTADAS.

Básicamente con una URL Se le otorga un montón de variables y un lugar para proporcionarle a una persona que se le proporciona, lo que proporciona está completamente depende 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 algunos ejemplos más de cómo hacerlo serían buenos, FormWizard es probablemente el lugar para comenzar.

 

Generic views will usually be the way to go, but ultimately you're free to handle URLs however you want. FormWizard does things in a class-based way, as do some apps for RESTful APIs.

Basically with a URL you are given a bunch of variables and place to provide a callable, what callable you provide is completely up to you - the standard way is to provide a function - but ultimately Django puts no restrictions on what you do.

I do agree that a few more examples of how to do this would be good, FormWizard is probably the place to start though.

</div
 
 
1
 
vote

Si desea compartir una funcionalidad común entre las páginas, le sugiero que vea las etiquetas personalizadas. Son bastante fácil de crear , y son muy Potente.

Además, Las plantillas pueden extenderse desde otras plantillas . Esto le permite tener una plantilla de base para configurar el diseño de la página y compartir esto entre otras plantillas que completen 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.

 

If you want to share common functionality between pages I suggest you look at custom tags. They're quite easy to create, and are very powerful.

Also, templates can extend from other templates. This allows you to have a base template to set up the layout of the page and to share this between other templates which fill in the blanks. You can nest templates to any depth; allowing you to specify the layout on separate groups of related pages in one place.

</div
 
 
 
 
1
 
vote

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

 

You can use the Django Generic Views. You can easily achieve desired functionality thorough Django generic Views

</div
 
 

Relacionados problema

2  Diseño lógico versus físico  ( Logical versus physical design ) 
Tengo una pregunta de diseño muy general, pero lo enmarcaré en términos concretos con un ejemplo. Supongamos que está trabajando en un software incrustado p...

0  Convención de nombres arbitrarios (objetos comerciales)  ( Arbitrary naming convention business objects ) 
OK, ¿realiza - (void)drawRect:(CGRect)rect0 o - (void)drawRect:(CGRect)rect111 - (void)drawRect:(CGRect)rect2 o - (void)drawRect:(CGRect)rect3 ¿Qué ...

682  Agregar un método a una instancia de objeto existente  ( Adding a method to an existing object instance ) 
He leído que es posible agregar un método a un objeto existente (es decir, no en la definición de clase) en Python. Entiendo que no siempre es bueno hacerlo...

56  ¿Debo usar clases anidadas en este caso?  ( Should i use nested classes in this case ) 
Estoy trabajando en una colección de clases utilizadas para la reproducción de video y la grabación. Tengo una clase principal que actúa como la interfaz públ...

13  ¿Cómo evitar las asignaciones / asignaciones sucesivas en C ++?  ( How to avoid successive deallocations allocations in c ) 
Considere el siguiente código: class A { B* b; // an A object owns a B object A() : b(NULL) { } // we don't know what b will be when constructing ...

98  ¿Cómo accedería a las propiedades de objetos desde un método de objeto? [cerrado]  ( How would you access object properties from within an object method ) 
Según lo que actualmente representa, esta pregunta no es un buen ajuste para nuestro Q & Amp; un formato. Esperamos que las...

21  ¿La clase inmutable debe ser definitiva?  ( Immutable class should be final ) 
dice en este artículo que: Haciendo una final de clase porque es inmutable es una buena razón para hacerlo. Estoy un poco desconcertado por esto ... E...

30  ¿Filtrado de spam bayesiano orientado a objetos?  ( Object oriented bayesian spam filtering ) 
Me preguntaba si hay alguna implementación de programación (OOP) orientada a objetos buena (OOP) de filtrado bayesiano para la clasificación de spam y texto? ...

53  Pasar por referencia o pasar por valor? [cerrado]  ( Pass by reference or pass by value ) 
Según lo que actualmente representa, esta pregunta no es un buen ajuste para nuestro Q & Amp; un formato. Esperamos que las...

55  Vistas de clase en Django  ( Class views in django ) 
django Ver puntos a una función, lo que puede ser un problema si quieres cambiar solo un poco de funcionalidad. Sí, podría tener un millón de argumentos de ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos