Django-filter: Filtrage par attribut de modèle de clé étrangère

Créé le 9 janv. 2019  ·  4Commentaires  ·  Source: carltongibson/django-filter

Salut!

Je travaillais sur un problème au travail et je me demandais quelle était la manière la plus idiomatique de l'aborder. Nous avons plusieurs champs de filtre ModelMultipleChoiceFilter pour les clés étrangères d'un modèle. J'essaie de comprendre comment filtrer par un attribut unique sur les clés étrangères tout en utilisant un widget CheckboxSelectMultiple , sans exposer les clés primaires dans les URL.

Voici un exemple qui montre (plus ou moins) comment je l'ai configuré en ce moment.

# app/models.py
from django.db import models

class Foo(models.Model):
    prop = models.CharField(max_length=55, unique=True)

    def __str__(self):
        return self.name


class Bar(models.Model):
    foo = models.ForeignKey(Foo, related_name="bars")
# app/filters.py
import django_filters
from app.models import Bar, Foo

class BarFilter(django_filters.FilterSet):
    foo = django_filters.ModelMultipleChoiceFilter(
        queryset=Foo.objects.all(),
        widget=CheckboxSelectMultiple(),
        label="Foo",
        label_suffix="",
    )

    class Meta:
        model = bar
        fields = ['foo']

Cela fonctionne très bien dans la vue. Les filtres fonctionnent et filtrent correctement avec les bons widgets. Cependant, l'url contient la clé primaire, donc dans cet exemple /?foo=1 , alors que je veux qu'elle lise /?foo=<prop value> , pour éviter d'exposer mon pk et rendre les URL plus lisibles.

J'ai essayé de modifier des champs comme celui-ci, car ailleurs dans Django, cela a tendance à fonctionner :

# app/filters.py
...snip...
    class Meta:
        model = bar
        fields = ['foo__prop']

Cela fait que l'url répond à /?foo=<prop value> comme vous le souhaitez, mais maintenant elle n'utilise pas CheckboxSelectMultiple pour le formulaire. J'ai également essayé de transformer l'attribut en foo__prop , mais le rendu du formulaire était toujours incorrect.

J'ai le sentiment que ce que j'essaie de faire est pris en charge étant donné que cela fonctionne presque, mais je n'arrive pas à comprendre comment l'obtenir. Si cela est en dehors de la portée actuellement prise en charge, je peux écrire mon propre formulaire pour gérer cela. Merci beaucoup pour toute aide et pour le projet génial!

Commentaire le plus utile

Bonjour, merci d'avoir pris le temps de répondre !

Vous m'avez mis sur la bonne voie ! J'ai eu la chance de l'implémenter hier, et l'utilisation de l'argument field_name fonctionné !

Pour toute personne susceptible de lire ce numéro à l'avenir, voici à peu près comment le code est sorti :

# app/filters.py
...snip
class BarFilter(django_filters.FilterSet):
    foo = django_filters.ModelMultipleChoiceFilter(
        queryset=Foo.objects.all(),
        field_name="foo__prop", # This lets us keep the url as "/?foo=<value>
        to_field_name="prop",
        widget=CheckboxSelectMultiple(),
        label="Foo",
        label_suffix="",
    )

    class Meta:
        model = bar
        fields = ['foo']

Vous pouvez trouver une référence à cela dans la documentation @carltongibson mentionnée en haut du fil. Plus précisément, consultez la section sur les filtres ModelMultipleChoice.

En tout cas merci beaucoup d'avoir pris le temps de m'aider !

Tous les 4 commentaires

Salut. Belle question. Strictement une question d'utilisation, mais si bien posée, c'est un plaisir à lire.

Avez-vous regardé l'argument field_name pour les filtres ?
https://django-filter.readthedocs.io/en/master/ref/filters.html

Cela vous permettrait d'utiliser foo_prop comme cible pour votre filtre foo.

J'imagine que cela fonctionnerait... peut-être que vous auriez besoin de définir des choix sur le widget ou autre (mais cela devrait être géré...)

Bonjour, merci d'avoir pris le temps de répondre !

Vous m'avez mis sur la bonne voie ! J'ai eu la chance de l'implémenter hier, et l'utilisation de l'argument field_name fonctionné !

Pour toute personne susceptible de lire ce numéro à l'avenir, voici à peu près comment le code est sorti :

# app/filters.py
...snip
class BarFilter(django_filters.FilterSet):
    foo = django_filters.ModelMultipleChoiceFilter(
        queryset=Foo.objects.all(),
        field_name="foo__prop", # This lets us keep the url as "/?foo=<value>
        to_field_name="prop",
        widget=CheckboxSelectMultiple(),
        label="Foo",
        label_suffix="",
    )

    class Meta:
        model = bar
        fields = ['foo']

Vous pouvez trouver une référence à cela dans la documentation @carltongibson mentionnée en haut du fil. Plus précisément, consultez la section sur les filtres ModelMultipleChoice.

En tout cas merci beaucoup d'avoir pris le temps de m'aider !

Super. Content que tu l'aies résolu. Bien fait!

Bon travail ! Merci !

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