Django-filter: Permet de remplacer la récupération d'un ensemble de requêtes dans un FilterSet

Créé le 21 juin 2017  ·  4Commentaires  ·  Source: carltongibson/django-filter

Le titre peut être un peu confus. Ce serait bien d'avoir une méthode générique filter qui est appelée chaque fois que le jeu de requêtes est récupéré et que le filtrage des champs est appliqué. Oui, je peux remplacer la propriété qs , d'abord obtenir un ensemble de requêtes filtré, puis appliquer des prélectures. Mais _il n'est pas clair si cela peut avoir des effets secondaires et les données transmises au filtre sont accessibles en toute sécurité._

Voilà mon cas d'utilisation.
Je filtre un ensemble de requêtes par une relation M2M (comme dans queryset.filter(items__field="foo") ). Cependant, je souhaite également que les éléments préchargés soient filtrés par ce champ.

En d'autres termes, mon filtre ressemble à ceci :

# In my filterset
def filter_items_by_field(self, queryset, name, value):
        queryset = queryset.all().filter(
            items__field=value,
        )
        prefetched_items = Prefetch(
            'items',
            Item.objects..filter(
                field=value,
            ),
        )
        return queryset.prefetch_related(prefetched_items)

# In my vieset
def get_queryset(self):
        queryset = super().get_queryset()
        # This should be applied everytime
        prefetched_items = Prefetch(
            'items',
            Item.objects..filter(
                another_field=some_value,
            ),
        )
        return queryset.prefetch_related(prefetched_items)

Un seul filtre comme celui-ci fonctionne comme prévu. Cependant, je peux avoir plusieurs filtres filter_items_by_* + je dois appliquer le même filtrage pour le jeu de requêtes de prefetch pour tous les filtres. Et les filtres multiples ne sont pas un problème, car ils s'excluent mutuellement dans mon cas. Mais un filtre + générique provoquera une exception.

Le fait est que je ne peux appliquer qu'une seule prélecture pour la même recherche. Donc, dans mon cas, je vais simplement obtenir une exception.

J'ai une solution de contournement temporaire pour ce problème : tous les filter_items_by_* effectuent un filtrage obligatoire lors de la prélecture.
Et dans filter_queryset (après l'application du filtrage), si items ne sont pas préchargés (ce qui est mauvais puisque j'inspecte les attributs protégés de l'ensemble de requêtes), j'applique le prélecture avec le filtrage obligatoire. Mais il devrait y avoir une meilleure façon de gérer des situations comme celle-ci.

J'espère que mon exemple est assez clair.

Commentaire le plus utile

Salut @Alexx-G. Une version 2.0 est encore une solution, mais il y aura des changements dans l'API qui répondront spécifiquement à cette question. En bref,

  • Vous voudrez remplacer la méthode .filter_queryset() . L'attribut .qs sera essentiellement responsable de l'appel de .filter_queryset() et de la mise en cache de son résultat.
  • Vous pouvez obtenir les valeurs de filtre pour la prélecture à partir de self.form.cleaned_data .

Tous les 4 commentaires

Salut @Alexx-G. Je pense que cela pourrait être possible avec une certaine coordination entre l'ensemble de filtres et les classes de filtres pertinentes. Essentiellement, le filtre ajouterait une instance Prefetch à son ensemble parent filtres FilterSet.qs appellerait alors simplement prefetch_related cas échéant.

Cela dit, quel est le cas d'utilisation pour cela? Je dirais qu'il existe probablement des endroits plus appropriés pour gérer la prélecture.

Je pense que cela pourrait être possible avec une certaine coordination entre l'ensemble de filtres et les classes de filtres pertinentes.

J'ai déjà résolu mon problème en remplaçant la propriété qs , mais encore une fois, ce n'est pas évident et ce n'est pas documenté. En d'autres termes, je ne peux pas être sûr que certains changements internes dans la classe de base n'affecteront pas mon ensemble de filtres (ok, j'ai épinglé la version, mais de toute façon..)

Cela dit, quel est le cas d'utilisation pour cela? Je dirais qu'il existe probablement des endroits plus appropriés pour gérer la prélecture.

Je crois avoir décrit ci-dessus mon cas d'utilisation. Cela n'a pas de sens de séparer le filtrage et la prélecture, car la prélecture dépend des filtres. Et si je les sépare, je devrai dupliquer les mêmes contrôles de filtres.

En d'autres termes, s'il y avait une description du contrat public de la propriété qs ou un crochet documenté pour cela, cela améliorerait la personnalisation de l'ensemble de filtres.

Salut @Alexx-G. Une version 2.0 est encore une solution, mais il y aura des changements dans l'API qui répondront spécifiquement à cette question. En bref,

  • Vous voudrez remplacer la méthode .filter_queryset() . L'attribut .qs sera essentiellement responsable de l'appel de .filter_queryset() et de la mise en cache de son résultat.
  • Vous pouvez obtenir les valeurs de filtre pour la prélecture à partir de self.form.cleaned_data .

Merci beaucoup pour vos efforts !

Cette page vous a été utile?
0 / 5 - 0 notes