Dada uma classe:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=20)
É possível e, em caso afirmativo, como ter um QuerySet que filtra com base em argumentos dinâmicos? Por exemplo:
# Instead of:
Person.objects.filter(name__startswith='B')
# ... and:
Person.objects.filter(name__endswith='B')
# ... is there some way, given:
filter_by = '{0}__{1}'.format('name', 'startswith')
filter_value = 'B'
# ... that you can run the equivalent of this?
Person.objects.filter(filter_by=filter_value)
# ... which will throw an exception, since `filter_by` is not
# an attribute of `Person`.
python
django
django-models
Brian M. Hunt
fonte
fonte
Um exemplo simplificado:
Em um aplicativo de pesquisa do Django, eu queria uma lista de seleção HTML mostrando usuários registrados. Mas como temos 5.000 usuários registrados, eu precisava de uma maneira de filtrar essa lista com base em critérios de consulta (como apenas pessoas que concluíram um determinado workshop). Para que o elemento da pesquisa seja reutilizável, eu precisava que a pessoa que cria a pergunta da pesquisa pudesse anexar esses critérios a essa pergunta (não deseja codificar a consulta no aplicativo).
A solução que eu encontrei não é 100% amigável (requer a ajuda de um técnico para criar a consulta), mas resolve o problema. Ao criar a pergunta, o editor pode inserir um dicionário em um campo personalizado, por exemplo:
Essa sequência é armazenada no banco de dados. No código de exibição, ele retorna como
self.question.custom_query
. O valor disso é uma string que se parece com um dicionário. Nós o transformamos novamente em um dicionário real com eval () e, em seguida, o colocamos no conjunto de consultas com ** kwargs:fonte
eval()
a importação de usuários é uma má ideia, mesmo se você confiar totalmente em seus usuários. Um campo JSON seria uma ideia melhor aqui.O Django.db.models.Q é exatamente o que você deseja do Django.
fonte
Q(**filters)
, se você desejar criar objetos Q dinamicamente, poderá colocá-los em uma lista e usá-los.filter(*q_objects)
ou usar os operadores bit a bit para combinar os objetos Q.Um formulário de pesquisa realmente complexo geralmente indica que um modelo mais simples está tentando descobrir o caminho.
Como exatamente você espera obter os valores para o nome e a operação da coluna? Onde você obtém os valores de
'name'
um'startswith'
?Um formulário de "pesquisa"? Você vai - o que? - escolha o nome de uma lista de nomes? Escolha a operação em uma lista de operações? Embora abertas, a maioria das pessoas acha isso confuso e difícil de usar.
Quantas colunas possuem esses filtros? 6? 12? 18?
Botões de filtro específicos. Espere ... É assim que o administrador do Django funciona. Filtros específicos são transformados em botões. E a mesma análise acima se aplica. Alguns filtros fazem sentido. Um grande número de filtros geralmente significa um tipo de primeira violação de forma normal.
Muitos campos semelhantes geralmente significam que deveria haver mais linhas e menos campos.
fonte