vues de classe dans Django

voix
48

Django points de vue à une fonction, qui peut être un problème si vous voulez changer seulement un peu de fonctionnalité. Oui, je pourrais avoir millions de mots clés et des arguments encore plus si les déclarations de la fonction, mais je pensais plutôt à une approche orientée objet.

Par exemple, j'ai une page qui affiche un utilisateur. Cette page est très similaire à la page qui affiche un groupe, mais il est toujours pas si semblable à utiliser juste un autre modèle de données. Groupe compte également des membres etc ...

Une façon serait de montrer des vues sur les méthodes de classe, puis étendre cette classe. Quelqu'un at-il essayé cette approche ou a une autre idée?

Créé 03/08/2008 à 16:55
source utilisateur
Dans d'autres langues...                            


9 réponses

voix
41

Je l' ai créé et utilisé mes propres classes de vue générique, définit __call__donc une instance de la classe est appelable. J'aime vraiment ça; alors que les vues génériques de Django permettent une personnalisation par des arguments de mots clés, OO vues génériques (si leur comportement est divisé en un certain nombre de méthodes distinctes) peuvent avoir beaucoup plus de personnalisation à grains fins par subclassing, ce qui me permet de me répéter beaucoup moins. (Je suis fatigué de réécrire le même créer / mettre à jour à tout moment vue logique que je dois modifier quelque chose des vues génériques de Django ne permettent pas tout à fait).

J'ai posté un code à djangosnippets.org .

Le seul véritable inconvénient que je vois est la prolifération des appels de méthodes internes, ce qui peut avoir un impact sur la performance quelque peu. Je ne pense pas que ce soit vraiment un problème; il est rare que le code Python exécution serait votre goulot d'étranglement dans une application Web.

Mise à jour : propres de Django vues génériques sont maintenant de classes.

MISE À JOUR : FWIW, j'ai changé mon opinion sur des vues basées sur les classes depuis cette réponse a été écrit. Après les avoir largement utilisé sur quelques projets, je pense qu'ils ont tendance à conduire à un code qui est satisfyingly sec pour écrire, mais très difficile à lire et à maintenir plus tard, parce que la fonctionnalité est répartie sur tant d'endroits différents, et les sous - classes sont si dépendants sur tous les détails de mise en œuvre des superclasses et mixins. Je me sens maintenant que TemplateResponse décorateurs et vue est une meilleure réponse pour décomposer le code de la vue.

Créé 29/08/2008 à 05:29
source utilisateur

voix
13

Je devais utiliser des vues sur la base de la classe, mais je voulais être en mesure d'utiliser le nom complet de la classe dans mon URLConf sans toujours avoir à instancier la classe de vue avant de l'utiliser. Ce qui m'a aidé était une métaclasse étonnamment 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)

Je peux maintenant deux instancier des classes de vue et d' utiliser les instances comme les fonctions d'affichage, ou je peux simplement pointer mon URLConf à ma classe et ont la métaclasse instancier (et appeler) la classe d'affichage pour moi. Cela fonctionne en vérifiant le premier argument __call__- si elle est une HttpRequest, elle doit être une requête HTTP réelle , car il serait absurde de attept instancier une classe de vue avec un HttpRequestexemple.

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

(J'ai posté un extrait de ce à http://djangosnippets.org/snippets/2041/ )

Créé 27/05/2010 à 14:02
source utilisateur

voix
9

Si vous affichez simplement les données à partir de modèles, pourquoi ne pas utiliser les Django vues génériques ? Ils sont conçus pour vous permettre de données d'exposition facile d'un modèle sans avoir à écrire votre propre point de vue et d'autres choses sur les URL mapping paramaters à vue, la récupération des données, le traitement des cas de pointe, ce qui rend la production, etc.

Créé 07/08/2008 à 11:44
source utilisateur

voix
3

Vous pouvez toujours créer une classe, substituez la __call__fonction et puis pointez le fichier URL à une instance de la classe. Vous pouvez jeter un oeil à la FormWizard classe pour voir comment cela se fait.

Créé 26/08/2008 à 12:38
source utilisateur

voix
2

Sauf si vous voulez faire quelque chose un peu complexe, en utilisant les vues génériques sont la voie à suivre. Ils sont beaucoup plus puissants que leur nom l'indique, et si vous êtes l'affichage des données de modèle vues génériques fera le travail.

Créé 11/08/2008 à 23:59
source utilisateur

voix
2

Me semble que vous essayez de combiner des choses qui ne devraient pas être combinés. Si vous devez faire un traitement différent à votre avis en fonction si elle est un objet utilisateur ou groupe que vous essayez de regarder alors vous devriez utiliser deux fonctions de vue différent.

D'autre part, il peut y avoir des idiomes communs que vous voudriez extraire de votre point de vue de type object_detail ... peut-être que vous pourriez utiliser un décorateur ou seulement des fonctions d'assistance?

-Dan

Créé 03/08/2008 à 18:40
source utilisateur

voix
1

Vous pouvez utiliser les Django Vues génériques. Vous pouvez facilement obtenir une fonctionnalité voulue Django complets vues génériques

Créé 08/10/2014 à 06:53
source utilisateur

voix
1

Les vues génériques seront généralement la voie à suivre, mais finalement, vous êtes libre de gérer les URL comme vous le voulez. FormWizard fait les choses d'une manière de classe, comme certaines applications pour les API RESTful.

Fondamentalement, avec une URL que vous donne un tas de variables et lieu de fournir un appelable, ce que vous fournissez appelable est complètement à vous - la méthode standard est de fournir une fonction - mais en fin de compte Django met pas de restrictions sur ce que vous faites.

Je suis d'accord que quelques autres exemples de la façon de le faire serait bon, FormWizard est probablement l'endroit pour commencer si.

Créé 23/09/2008 à 20:05
source utilisateur

voix
1

Si vous souhaitez partager des fonctionnalités communes entre les pages que je vous suggère de regarder des balises personnalisées. Ils sont assez faciles à créer et sont très puissants.

En outre, les modèles peuvent étendre d'autres modèles . Cela vous permet d'avoir un modèle de base pour mettre en place la mise en page de la page et de partager ce entre autres modèles qui remplissent les espaces vides. Vous pouvez imbriquer des modèles à une profondeur; vous permettant de spécifier la disposition des groupes distincts de pages liées à un seul endroit.

Créé 26/08/2008 à 12:30
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more