python - Vues de classe à Django

Translate

Djangoview pointe vers une fonction, ce qui peut poser problème si vous ne souhaitez modifier qu'un peu de fonctionnalité. Oui, je pourrais avoir des millions d'arguments de mots-clés et même plus d'instructions if dans la fonction, mais je pensais davantage à 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 ce n'est toujours pas si similaire à utiliser simplement un autre modèle de données. Le groupe a aussi des membres etc ...

Une façon serait de pointer des vues vers des méthodes de classe, puis d'étendre cette classe. Quelqu'un a-t-il essayé cette approche ou a-t-il une autre idée?

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

J'ai créé et utilisé mes propres classes de vue génériques, définissant__call__donc une instance de la classe peut être appelée. J'aime vraiment ça; alors que les vues génériques de Django permettent une certaine personnalisation via des arguments de mots clés, les vues génériques OO (si leur comportement est divisé en plusieurs méthodes distinctes) peuvent avoir une personnalisation beaucoup plus fine via le sous-classement, ce qui me permet de me répéter beaucoup moins. (Je suis fatigué de réécrire la même logique de création / mise à jour de vue chaque fois que j'ai besoin de modifier quelque chose que les vues génériques de Django ne permettent pas tout à fait).

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

Le seul vrai inconvénient que je vois est la prolifération des appels de méthode internes, ce qui peut avoir un impact sur les performances. Je ne pense pas que ce soit vraiment un problème; il est rare que l'exécution de code Python soit votre goulot d'étranglement de performances dans une application Web.

METTRE À JOUR: Le propre de Djangovues génériquessont désormais basés sur les classes.

METTRE À JOUR: FWIW, j'ai changé d'avis sur les vues basées sur les classes depuis que cette réponse a été écrite. Après les avoir beaucoup utilisés sur quelques projets, je pense qu'ils ont tendance à conduire à un code qui est satisfaisant DRY à écrire, mais très difficile à lire et à maintenir plus tard, car les fonctionnalités sont réparties à travers tellement d'endroits différents et les sous-classes sont tellement dépendantes. sur chaque détail d'implémentation des superclasses et des mixins. Je sens maintenant queTemplateResponseet les décorateurs de vues sont une meilleure réponse pour décomposer le code de vue.

La source
Translate

J'avais besoin d'utiliser des vues basées sur les classes, mais je voulais pouvoir utiliser le nom complet de la classe dans mon URLconf sans avoir toujours à 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 à la fois instancier les classes de vue et utiliser les instances comme fonctions de vue, OU je peux simplement pointer mon URLconf vers ma classe et demander à la métaclasse d'instancier (et d'appeler) la classe de vue pour moi. Cela fonctionne en vérifiant le premier argument de__call__- si c'est unHttpRequest, il doit s'agir d'une requête HTTP réelle car il serait absurde de tenter d'instancier une classe de vueHttpRequestexemple.

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 publié un extrait à ce sujet àhttp://djangosnippets.org/snippets/2041/)

La source
Translate

Si vous affichez simplement des données de modèles, pourquoi ne pas utiliserVues génériques Django? Ils sont conçus pour vous permettre d'afficher facilement les données d'un modèle sans avoir à écrire votre propre vue et des informations sur le mappage des paramètres d'URL aux vues, la récupération de données, la gestion des cas extrêmes, le rendu de la sortie, etc.

La source
Translate

Vous pouvez toujours créer une classe, remplacer le__call__puis pointez le fichier URL vers une instance de la classe. Vous pouvez jeter un oeil à laFormWizardclasse pour voir comment cela est fait.

La source
Lynn Lee
Translate

Il me semble que vous essayez de combiner des choses qui ne devraient pas être combinées. Si vous devez effectuer un traitement différent dans votre vue selon qu'il s'agit d'un objet Utilisateur ou Groupe que vous essayez d'examiner, vous devez utiliser deux fonctions d'affichage différentes.

D'un autre côté, il peut y avoir des idiomes courants que vous voudriez extraire de vos vues de type object_detail ... peut-être pourriez-vous utiliser un décorateur ou simplement des fonctions d'aide?

-Dan

La source
Translate

À moins que vous ne souhaitiez faire quelque chose d'un peu complexe, l'utilisation des vues génériques est la voie à suivre. Ils sont beaucoup plus puissants que leur nom ne l'indique, et si vous affichez simplement des données de modèle, des vues génériques feront l'affaire.

La source
Translate

Les vues génériques sont généralement la solution, mais en fin de compte, vous êtes libre de gérer les URL comme vous le souhaitez. FormWizard fait les choses d'une manière basée sur les classes, tout comme certaines applications pour les API RESTful.

Fondamentalement, avec une URL, on vous donne un tas de variables et un endroit pour fournir un appelable, ce que vous fournissez est entièrement à vous - la manière standard est de fournir une fonction - mais finalement Django ne met aucune restriction sur ce que vous faites.

Je suis d'accord pour dire que quelques autres exemples de la façon de procéder seraient bien, FormWizard est probablement le point de départ.

La source
Translate

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

Également,les modèles peuvent s'étendre à partir d'autres modèles. Cela vous permet d'avoir un modèle de base pour configurer la mise en page de la page et de le partager entre d'autres modèles qui remplissent les espaces. Vous pouvez imbriquer des modèles à n'importe quelle profondeur; vous permettant de spécifier la mise en page sur des groupes séparés de pages associées en un seul endroit.

La source
Translate

Vous pouvez utiliser les vues génériques Django. Vous pouvez facilement obtenir les fonctionnalités souhaitées grâce aux vues génériques Django

La source