¡Hola!
Estaba trabajando en un problema en el trabajo y me preguntaba cuál es la forma más idiomática de abordarlo. Tenemos varios campos de filtro ModelMultipleChoiceFilter
para claves externas de un modelo. Estoy tratando de averiguar cómo filtrar por un atributo único en las claves externas mientras uso un widget CheckboxSelectMultiple
, sin exponer las claves primarias en las URL.
Aquí hay un ejemplo que (más o menos) muestra cómo lo tengo configurado en este momento.
# 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']
Esto funciona totalmente bien en la vista. Los filtros funcionan y filtran correctamente con los widgets adecuados. Sin embargo, la URL tiene la clave principal, por lo que en este ejemplo /?foo=1
, mientras que quiero que se lea /?foo=<prop value>
, para evitar exponer mi pk y hacer que las URL sean más legibles.
Intenté modificar campos como este, porque en otras partes de Django tiende a funcionar:
# app/filters.py
...snip...
class Meta:
model = bar
fields = ['foo__prop']
Esto hace que la URL responda a /?foo=<prop value>
como se desee, pero ahora no usa CheckboxSelectMultiple
para el formulario. Intenté convertir el atributo en foo__prop
también, pero la representación del formulario seguía siendo incorrecta.
Tengo la sensación de que lo que estoy tratando de hacer es compatible teniendo en cuenta que casi funciona, pero parece que no puedo averiguar cómo conseguirlo. Si esto está fuera del alcance admitido actual, puedo escribir mi propio formulario para manejar esto. ¡Muchas gracias por la ayuda y por el fantástico proyecto!
Hola. Buen tema. Estrictamente una pregunta de uso, pero tan bien expresada, es un placer leerla.
¿Miraste el argumento field_name para los filtros?
https://django-filter.readthedocs.io/en/master/ref/filters.html
Esto le permitiría usar foo_prop como objetivo para su filtro foo.
Me imagino que eso simplemente funcionaría ... tal vez debas establecer opciones en el widget o algo así (pero eso debería manejarse ...)
Hola, gracias por tomarse el tiempo para responder.
¡Me has puesto en el camino correcto! Tuve la oportunidad de implementar esto ayer, ¡y usar el argumento field_name
funcionó!
Para cualquiera en el futuro que pueda leer este número, así es aproximadamente como salió el código:
# 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']
Puede encontrar una referencia a esto en la documentación que @carltongibson mencionó. Específicamente, consulte la sección sobre filtros ModelMultipleChoice.
De todos modos, ¡muchas gracias por tomarse el tiempo para ayudarme!
Súper. Me alegro de que lo hayas resuelto. ¡Bien hecho!
Gran trabajo ! Gracias !
Comentario más útil
Hola, gracias por tomarse el tiempo para responder.
¡Me has puesto en el camino correcto! Tuve la oportunidad de implementar esto ayer, ¡y usar el argumento
field_name
funcionó!Para cualquiera en el futuro que pueda leer este número, así es aproximadamente como salió el código:
Puede encontrar una referencia a esto en la documentación que @carltongibson mencionó. Específicamente, consulte la sección sobre filtros ModelMultipleChoice.
De todos modos, ¡muchas gracias por tomarse el tiempo para ayudarme!