2010-11-11 7 views
0

Je remplace dynamiquement la fonction get_query_set de Django sur l'un de mes modèles. Je fais ceci pour filtrer de force l'ensemble de requêtes original retourné par Model.objects.all/filter/get par une valeur "scenario", en utilisant un décorateur. Voici la fonction du décorateur:Le remplacement de Django get_query_set est mis en cache

# Get the base QuerySet for these models before we modify their 
# QuerySet managers. This prevents infinite recursion since the 
# get_query_set function doesn't rely on itself to get this base QuerySet. 
all_income_objects = Income.objects.all() 

# Figure out what scenario the user is using. 
current_scenario = Scenario.objects.get(user=request.user, selected=True) 

# Modify the imported income class to filter based on the current scenario. 
Expense.objects.get_query_set = lambda: all_expense_objects.filter(scenario=current_scenario) 

# Call the method that was initially supposed to 
# be executed before we were so rudely interrupted. 
return view(request, **arguments) 

que je fais cela pour tarir le code, de sorte que toutes mes requêtes ne sont pas jonchées avec un filtre supplémentaire. Cependant, si le scénario change, aucun objet n'est retourné. Si je mets tous mes processus python sur mon serveur, les objets du scénario nouvellement sélectionné apparaissent. Je pense qu'il met en cache la classe modifiée, puis lorsque le scénario change, il applique un autre filtre qui n'aura jamais de sens, puisque les objets ne peuvent avoir qu'un seul scénario à la fois.

Cela n'a pas été un problème avec les filtres basés sur l'utilisateur car l'utilisateur ne change jamais pour ma session. Le passager fait-il quelque chose de stupide pour conserver des objets de classe entre les demandes? Devrais-je me débarrasser de ce modèle de conception étrange et juste mettre en œuvre ces filtres sur une base par vue? Il doit y avoir une meilleure pratique pour DRYing des filtres qui s'appliquent à travers de nombreuses vues basées sur quelque chose de dynamique, comme l'utilisateur actuel.

+0

Je ne vois pas où est le décorateur? – Unode

Répondre

0

Qu'en est-il de la création d'un objet Manager pour le modèle qui prend l'utilisateur comme argument où ce filtrage est effectué. Ma compréhension de l'être DRY w/Django QuerySets est d'utiliser un Model Manager

#### view code: 
def some_view(request): 
    expenses = Expense.objects.filter_by_cur_scenario(request.user) 

    # add additional filters here, or add to manager via more params 
    expenses = expenses.filter(something_else=True) 

#### models code: 
class ExpenseManager(models.Manager): 
    def filter_by_cur_scenario(self, user): 
     current_scenario = Scenario.objects.get(user=request.user, selected=True) 
     return self.filter(scenario=current_scenario) 

class Expense(models.Model): 
    objects = ExpenseManager() 

En outre, une mise en garde rapide sur le gestionnaire (qui peut demander à impérieuses get_query_set): relations avec l'étranger ne prendra pas en compte de tout filtrage fait à ce niveau. Par exemple, vous remplacez la méthode MyObject.objects.filter() pour toujours filtrer les lignes supprimées; Un modèle w/un étranger à cela n'utilisera pas cette fonction de filtre (au moins de ce que je comprends - quelqu'un s'il vous plaît corrigez-moi si je me trompe).

0

J'espérais que cette implémentation se produise sans avoir à coder quoi que ce soit dans d'autres vues. Essentiellement, après que la classe est importée, je veux la modifier afin que, peu importe où elle est référencée en utilisant Expense.objects.get/filter/all, elle a déjà été filtrée. Par conséquent, aucune implémentation n'est requise pour les autres vues. c'est complètement transparent. Et, même dans les cas où je l'utilise en tant que ForeignKey, lorsqu'un objet est récupéré en utilisant le fichier Expense.objects.get/filter/all mentionné ci-dessus, il sera également filtré.

Questions connexes