Indo pelas estrelas, django-taggit é tão popular quanto django-filter, e eu acredito que é a solução ideal para marcação em Django. Ele existe desde 2010, é atualizado regularmente e tem vários colaboradores regulares.
O que você acha de um filtro django-taggit?
O mais próximo que tenho disso é:
tags = django_filters.ModelMultipleChoiceFilter(
name='tags__name',
to_field_name='name',
conjoined=True,
distinct=True,
queryset=Tag.objects.all(),
)
Mas eu não posso fazer distinção entre maiúsculas e minúsculas (um filtro para a tag 'TeSt' deve retornar resultados com a tag 'teste').
Como o TaggitFilter
seria diferente de um ModelMultipleChoiceFilter
normal?
Além disso, tenho certeza de que poderíamos adicionar suporte lookup_expr
aqui simplesmente juntando o nome do campo com a pesquisa.
Com ModelMultipleChoiceFilter
o URL deve ser field_name=tag1&field_name=tag2
, mas pode haver um número significativo de tags, tornando o URL muito longo. Não é ideal para um URL que pode ser compartilhado, por exemplo.
As tags são processadas por django-taggit usando um conjunto de regras , permitindo que uma única string seja passada contendo todas as tags.
Independentemente disso, lookup_expr
em ModelMultipleChoiceFilter
seria definitivamente útil!
Uma olhada rápida indica que você deve ser capaz de usar TagsField
do Taggit. Isso lhe daria o comportamento de análise csv.
class TagsFilter(CharFilter):
field_class = taggit.forms.TagsField
def __init__(self, *args, **kwargs):
kwargs.setdefault('lookup_expr', 'in')
class MyFilterSet(FilterSet):
tags = TagsFilter(name='tags__name')
class Meta:
model = MyModel
GET http://localhost/api/my-model?tags=a,b,c,d
A ressalva aqui é que isso usa uma pesquisa in
, que não é a solução que não diferencia maiúsculas de minúsculas que você está procurando.
Estou mais ou menos na mente de não adicionar um filtro específico para Django Taggit, por melhor que seja o pacote.
Em última análise, criar filtros de nível de projeto não é tão difícil. Uma essência decente seria um longo caminho. (O Google é ótimo para eles.)
Fico feliz em olhar para uma solicitação de pull A +, se uma aparecer, mas, longe disso, fecharei isso como fora do escopo.
OK, é justo. E quanto ao suporte para lookup_expr
em ModelMultipleChoiceFilter
?
@stantond Feliz em olhar para um PR. _Mostre-me o Cödz_ 😀
Eu gostaria de poder - infelizmente não sou um desenvolvedor habilidoso, mas um PM desajeitado!
+1
Exemplo de trabalho com as bibliotecas mais recentes:
from taggit.forms import TagField
from django_filters.views import FilterView
class TagFilter(django_filters.CharFilter):
field_class = TagField
def __init__(self, *args, **kwargs):
kwargs.setdefault('lookup_expr', 'in')
super().__init__(*args, **kwargs)
class MyFilter(django_filters.FilterSet):
tags = TagFilter(field_name='tags__name')
class Meta:
model = MyModel
Use o campo slug
do Tag em vez do campo name
para não diferenciar maiúsculas de minúsculas. Taggit reduz os slugs por padrão.
Observe que podemos expandir a solução em https://github.com/carltongibson/django-filter/issues/460#issuecomment -507218839 com um campo personalizado se desejarmos oferecer suporte ao filtro por uma única tag que contenha um ou mais espaços em branco.
from django import forms
from django.utils.translation import gettext as _
from taggit.utils import parse_tags
class TagField(forms.CharField):
def clean(self, value):
value = super().clean(value)
if "," not in value and '"' not in value and value:
return [value]
try:
return parse_tags(value)
except ValueError:
raise forms.ValidationError(
_("Please provide a comma-separated list of tags.")
)
O código é extraído de taggit/forms.py
.
Comentários muito úteis
Exemplo de trabalho com as bibliotecas mais recentes: