Django-filter: Filtrando por Atributo de Modelo de Chave Estrangeira

Criado em 9 jan. 2019  ·  4Comentários  ·  Fonte: carltongibson/django-filter

Olá!

Eu estava trabalhando em um problema no trabalho e me perguntando qual é a maneira mais idiomática de lidar com isso. Temos vários campos de filtro ModelMultipleChoiceFilter para chaves estrangeiras de um modelo. Estou tentando descobrir como filtrar por um atributo exclusivo nas chaves estrangeiras enquanto uso um widget CheckboxSelectMultiple , sem expor as chaves primárias nas URLs.

Aqui está um exemplo que (mais ou menos) mostra como eu o tenho configurado agora.

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

Isso funciona perfeitamente bem no modo de exibição. Os filtros funcionam e filtram corretamente com os widgets certos. No entanto, o url contém a chave primária, portanto, neste exemplo /?foo=1 , embora eu queira ler /?foo=<prop value> , para evitar a exposição do meu pk e também para tornar os urls mais legíveis.

Tentei modificar campos como este, porque em outros lugares no Django tende a funcionar:

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

Isso faz com que a url responda a /?foo=<prop value> conforme desejado, mas agora não usa CheckboxSelectMultiple para o formulário. Tentei transformar o atributo em foo__prop também, mas a renderização do formulário ainda estava incorreta.

Tenho a sensação de que o que estou tentando fazer é apoiado, considerando que está quase funcionando, mas não consigo descobrir como fazer isso. Se estiver fora do escopo com suporte atual, posso escrever meu próprio formulário para lidar com isso. Muito obrigado por qualquer ajuda e pelo projeto incrível!

Comentários muito úteis

Olá, obrigado por responder!

Você me colocou no caminho certo! Tive a chance de implementar isso ontem e usar o argumento field_name funcionou!

Para qualquer pessoa no futuro que possa ler este problema, veja aproximadamente como o código saiu:

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

Você pode encontrar uma referência a isso na documentação @carltongibson mencionado no tópico. Especificamente, consulte a seção sobre filtros ModelMultipleChoice.

De qualquer forma, muito obrigado por dedicar seu tempo para me ajudar!

Todos 4 comentários

Hiya. Belo problema. Uma pergunta estritamente de uso, mas bem colocada, é um prazer ler.

Você olhou para o argumento field_name para filtros?
https://django-filter.readthedocs.io/en/master/ref/filters.html

Isso permitiria a você usar foo_prop como alvo para seu filtro foo.

Eu imagino que isso simplesmente funcione ... talvez você precise definir opções no widget ou algo assim (mas isso deve ser tratado ...)

Olá, obrigado por responder!

Você me colocou no caminho certo! Tive a chance de implementar isso ontem e usar o argumento field_name funcionou!

Para qualquer pessoa no futuro que possa ler este problema, veja aproximadamente como o código saiu:

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

Você pode encontrar uma referência a isso na documentação @carltongibson mencionado no tópico. Especificamente, consulte a seção sobre filtros ModelMultipleChoice.

De qualquer forma, muito obrigado por dedicar seu tempo para me ajudar!

Super. Que bom que você resolveu. Bem feito!

Bom trabalho ! Obrigado !

Esta página foi útil?
0 / 5 - 0 avaliações