2010-02-22 6 views
2

Désolé ou le titre déroutant! C'est en fait beaucoup plus simple que ça en a l'air.Fonction de contexte de modèle Django sans courir automatiquement

J'ai une fonction:

def get_messages(request): 
    # do something expensive with the request 
    return 'string' 

Je veux être en mesure d'appeler cette fonction à partir du modèle, donc j'ai sanglé avec un processeur de contexte:

def context_processor(request): 
    return {'messages':get_messages(request)} 

Alors maintenant quand j'ai {{messages}} dans mon modèle, string imprime. Génial.

Le problème est est assez cher et n'est pas toujours nécessaire. Moins de la moitié des modèles en ont besoin. Existe-t-il un moyen de passer la fonction au modèle et de le laisser au modèle s'il s'exécute ou non?

J'ai essayé déjà:

def context_processor(request): 
    return {'messages':get_messages} 

Mais que juste sorties de la description de la fonction <function get_messages at 0x23e97d0> dans le modèle au lieu de l'exécuter.

Répondre

3

Je pense que vous ne devriez pas mélanger la logique de l'application avec le modèle (la vue dans le modèle MVC). Cela brise la cohérence de l'architecture. Vous pouvez appeler get_messages dans les vues qui en ont besoin et simplement passer messages au contexte du modèle, dans les autres, il suffit de passer None.

Mais répondre à Votre question: Vous pouvez créer un objet proxy. Par exemple:

class Proxy(object): 
    def __init__(self, request) 
     self.request = request 
     super(Proxy, self).__init__() 

    def get_messages(self): 
     # so some expensive things 
     return 'string' 

# context processor 
def context_processor(request): 
    return {'messages':Proxy(request)} 

# in the view 
{{ messages.get_messages }} 

Vous pouvez faire ce toujours plus générique, et de créer la classe proxy qui a une méthode (par exemple get), et prend un paramètre dans le constructeur: une fonction qui prend l'objet de demande en tant que premier paramètre. De cette façon, vous gagnez une méthode générique pour le proxy d'un appel de fonction dans vos modèles. Ici, il est:

class Proxy(object): 
    def __init__(self, request, function) 
     self.request = request 
     self.function = function 
     super(Proxy, self).__init__() 

    def get(self): 
     return self.function(self.request) 

Vous pouvez alors écrire encore plus cool que je l'avais écrit avant:

# context processor 
def context_processor(request): 
    return {'messages':Proxy(request, get_messages)} 

# sounds nice to me 
{{ messages.get }} 
+1

Cette solution juste me vint à l'extérieur tout en ayant une cigarette pensive. Je ne prends pas de crédit, mais je dis simplement: je suis entièrement d'accord. Cela ressemble à la meilleure solution disponible! – Oli

Questions connexes