Django-filter: Filtern nach Attribut des Fremdschlüsselmodells

Erstellt am 9. Jan. 2019  ·  4Kommentare  ·  Quelle: carltongibson/django-filter

Hi!

Ich habe bei der Arbeit an einem Problem gearbeitet und mich gefragt, wie man es am idiomatischsten angeht. Wir haben mehrere ModelMultipleChoiceFilter Filterfelder für Fremdschlüssel eines Modells. Ich versuche herauszufinden, wie man bei Verwendung eines CheckboxSelectMultiple Widgets nach einem eindeutigen Attribut für die Fremdschlüssel filtert, ohne Primärschlüssel in den URLs offenzulegen.

Hier ist ein Beispiel, das (mehr oder weniger) zeigt, wie ich es gerade eingerichtet habe.

# 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']

Das funktioniert in der Ansicht ganz gut. Die Filter funktionieren und filtern korrekt mit den richtigen Widgets. Die URL enthält jedoch den Primärschlüssel, also in diesem Beispiel /?foo=1 , während ich möchte, dass sie /?foo=<prop value> lautet, um zu verhindern, dass mein pk preisgegeben wird und URLs lesbarer werden.

Ich habe versucht, Felder wie folgt zu ändern, weil es anderswo in Django dazu neigt, zu funktionieren:

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

Dadurch reagiert die URL wie gewünscht auf /?foo=<prop value> , verwendet aber jetzt nicht mehr CheckboxSelectMultiple für das Formular. Ich habe auch versucht, das Attribut zu foo__prop zu machen, aber das Rendern des Formulars war immer noch falsch.

Ich habe das Gefühl, dass das, was ich versuche, unterstützt wird, wenn man bedenkt, dass es fast funktioniert, aber ich kann nicht ganz herausfinden, wie ich es hinbekomme. Wenn dies außerhalb des derzeit unterstützten Bereichs liegt, kann ich mein eigenes Formular schreiben, um dies zu handhaben. Vielen Dank für jede Hilfe und für das tolle Projekt!

Hilfreichster Kommentar

Hallo, vielen Dank, dass Sie sich die Zeit genommen haben zu antworten!

Sie haben mich auf den richtigen Weg gebracht! Ich hatte gestern die Gelegenheit, dies zu implementieren, und die Verwendung des Arguments field_name funktioniert!

Für alle, die dieses Problem in Zukunft lesen könnten, hier ungefähr, wie der Code herausgekommen ist:

# 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']

Einen Hinweis darauf finden Sie in der Dokumentation @carltongibson, die oben erwähnt wurde. Siehe insbesondere den Abschnitt zu ModelMultipleChoice-Filtern.

Trotzdem vielen Dank, dass Sie sich die Zeit genommen haben, mir zu helfen!

Alle 4 Kommentare

Hallo. Schöne Angelegenheit. Streng genommen eine Verwendungsfrage, aber so gut formuliert, dass es ein Vergnügen ist, es zu lesen.

Haben Sie sich das Argument field_name für Filter angesehen?
https://django-filter.readthedocs.io/en/master/ref/filters.html

Auf diese Weise können Sie foo_prop als Ziel für Ihren foo-Filter verwenden.

Ich könnte mir vorstellen, dass das einfach funktioniert ... vielleicht müssen Sie Optionen für das Widget oder so einstellen (aber das sollte behandelt werden ...)

Hallo, vielen Dank, dass Sie sich die Zeit genommen haben zu antworten!

Sie haben mich auf den richtigen Weg gebracht! Ich hatte gestern die Gelegenheit, dies zu implementieren, und die Verwendung des Arguments field_name funktioniert!

Für alle, die dieses Problem in Zukunft lesen könnten, hier ungefähr, wie der Code herausgekommen ist:

# 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']

Einen Hinweis darauf finden Sie in der Dokumentation @carltongibson, die oben erwähnt wurde. Siehe insbesondere den Abschnitt zu ModelMultipleChoice-Filtern.

Trotzdem vielen Dank, dass Sie sich die Zeit genommen haben, mir zu helfen!

Super. Schön, dass du es gelöst hast. Gut erledigt!

Gut gemacht ! Dankeschön !

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

lalzada picture lalzada  ·  3Kommentare

csarcom picture csarcom  ·  3Kommentare

nhuzaa picture nhuzaa  ·  3Kommentare

edmorley picture edmorley  ·  3Kommentare

sassanh picture sassanh  ·  4Kommentare