Question

Je me déplace d'un fond de PHP dans le développement de Django via python, principalement à cause de la lutte contre un MVC (ou MVT) que je me sens le plus logique, bien que dans ce modèle que j'ai commencé à remarquer beaucoup de le code répété dans mes vues.

Par exemple, lorsque vous êtes connecté j'ai des informations concernant l'utilisateur que je voudrais apparaître sur chaque page, bien que lors de l'utilisation render_to_response et dans chaque vue cela est nécessaire, je dois saisir les informations et le transmettre à la fonction render_to_response.

Je me demande quelle serait la façon la plus efficace de réduire le code en double qui, en substance nécessaire dans toutes les vues dans une application particulière.

Merci d'avance.

Était-ce utile?

La solution

Personnellement, je suis un grand fan de décorateurs, qui sont une caractéristique de python qui est pas spécifique à Django. Les décorateurs sont le sucre syntaxique parfait sur des fonctions d'ordre supérieur, et ils sont particulièrement utiles pour réduire boilerplate dans les vues - vous pouvez définir rapidement une fonction enveloppe généralisée, dans lequel vous pouvez mettre le code répétitif pour une réutilisation facile et une pratique refactoring -stop.

Il est probablement plus facile de vous montrer que d'expliquer comment ils fonctionnent. Voici une vue simplifiée par exemple:

def listpage(request):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.filter(visible=True).order_by("-modifydate")
    }))

def itemlist_tags(request, tags):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
    }))

... mais que vous vouliez faire ces pages obligent l'utilisateur à ouvrir une session Vous pouvez ajouter le code de connexion comme ceci:.

def listpage(request):
    if not request.user.is_authenticated():
        return f(request, *args, **kwargs)
    else:
        return HttpResponse(render_to_string("itemlist.html", {
            "items": Item.objects.filter(visible=True).order_by("-modifydate")
        }))

def itemlist_tags(request, tags):
    if not request.user.is_authenticated():
        return f(request, *args, **kwargs)
    else:
        return HttpResponse(render_to_string("itemlist.html", {
            "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
        }))

... qui commence à se notamment plus grand et répétitif, même pour un exemple artificiel. Vous pouvez faire vos fonctions à nouveau mince avec des décorateurs, comme suit:

du décorateur décorateur d'importation

@decorator
def loginrequired(f, request, *args, **kwargs):
    if request.user.is_authenticated():
        return f(request, *args, **kwargs)
    else:
        return HttpResponseRedirect("/")

@loginrequired
def listpage(request):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.filter(visible=True).order_by("-modifydate")
    }))

    @loginrequired
def itemlist_tags(request, tags):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
    }))

@loginrequired
def another_such_function(request):
    (...)

@loginrequired
def and_again(request):
    (...)

Qu'est-ce qui se passe est la fonction décorateur est exécutée au moment de la définition de la fonction. Le « f » dans mon exemple est un objet représentant la fonction que le décorateur est appliquée, que vous pouvez manipuler de manière sans fin.

Cela nécessite décorateur bibliothèque, qui est disponible sur PyPI comme beaucoup de bons morceaux de python , tu trouveras.

Vous n'avez pas besoin de cette bibliothèque pour écrire des fonctions de décorateur, mais il est utile, surtout au début. Ils peuvent faire ensemble beaucoup plus - tout appelable peut être un décorateur; vous pouvez décorer les méthodes de classe et d'intercepter la variable self; décorateurs peuvent être enchaînées, comme suit:

@second
@first
def originalfunction(*args):
    (...)

Je vais laisser l'exploration de ce que vous pouvez faire avec cette fonction d'ordre supérieur facile manpipulation pour vous, si cette notion aiguiser votre appétit. J'ai beaucoup d'autres exemples aussi bien, pour vous ou tout autre curieux de nouveaux amateurs de python. Bonne chance.

Autres conseils

Encapsuler le code commun dans une fonction et l'appeler de différents points de vue. Ça a l'air trivial, mais il est la solution pour 99% de ces besoins.

Pour une réponse plus précise, vous devrez montrer un exemple plus concret du code que vous voulez exécuter.

Il y a deux façons principales pour abstraire sur le contenu commun.

processeurs de contexte sont les meilleurs pour passer bits de données que vous savez que vous aurez besoin sur tous les plans unique.

balises modèle - en particulier les balises d'inclusion - sont utiles pour le rendu des zones séparées de la page qui sera le même sur plusieurs modèles.

En outre, ne pas oublier vues génériques ! Dans 90% des cas, vous pouvez envelopper object_list ou object_detail et vous épargner un peu de code.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top