Como faço para executar a filtragem de consulta em modelos de Django

votos
65

Eu preciso executar uma consulta filtrada a partir de um modelo de Django, para obter um conjunto de objetos equivalentes ao código python dentro de um ponto de vista:

queryset = Modelclass.objects.filter(somekey=foo)

No meu modelo que eu gostaria de fazer

{% for object in data.somekey_set.FILTER %}

mas eu simplesmente não consigo descobrir como escrever FILTER.

Publicado 22/10/2008 em 00:55
fonte usuário
Em outras línguas...                            


5 respostas

votos
102

Você não pode fazer isso, o que é próprio do projeto. Os autores framework Django destina uma estrita separação de código de apresentação da lógica de dados. modelos de filtragem é a lógica de dados e saída HTML é a lógica de apresentação.

Então, você tem várias opções. O mais fácil é fazer a filtragem, em seguida, passar o resultado para render_to_response. Ou você poderia escrever um método em seu modelo de modo que você pode dizer {% for object in data.filtered_set %}. Finalmente, você pode escrever sua própria marca de modelo, embora neste caso específico gostaria de aconselhar contra isso.

Respondeu 22/10/2008 em 01:00
fonte usuário

votos
24

Eu só adicionar um tag extra, como este:

@register.filter
def in_category(things, category):
    return things.filter(category=category)

Então eu posso fazer:

{% for category in categories %}
  {% for thing in things|in_category:category %}
    ` thing `
  {% endfor %}
{% endfor %}
Respondeu 07/05/2013 em 22:41
fonte usuário

votos
11

Eu executar para esse problema em uma base regular e muitas vezes usam a solução "adicionar um método". No entanto, há definitivamente casos em "Adicionar um método" ou "computam-lo na vista" não funcionam (ou não funcionam bem). Por exemplo, quando você está cache de fragmentos de modelo e precisam de alguma computação DB não-trivial para produzi-lo. Você não quer fazer o trabalho DB a menos que você precisa, mas você não vai saber se você precisa até que você está no fundo a lógica do modelo.

Algumas outras soluções possíveis:

  1. Use o {% expr <expressão> como <var_name>%} tag encontrada em http://www.djangosnippets.org/snippets/9/ A expressão é qualquer expressão Python legal com contexto do seu modelo como o seu âmbito local.

  2. Alterar o seu processador de modelo. Jinja2 ( http://jinja.pocoo.org/2/ ) tem uma sintaxe que é quase idêntico ao modelo de linguagem Django, mas com poder Python completo disponível. É também mais rápido. Você pode fazer isso por atacado, ou você pode limitar seu uso para modelos que você está trabalhando, mas usar modelos "mais seguras" do Django para páginas manteve-designer.

Respondeu 23/10/2008 em 18:22
fonte usuário

votos
8

Isso pode ser resolvido com uma etiqueta de atribuição:

from django import template

register = template.Library()

@register.assignment_tag
def query(qs, **kwargs):
    """ template tag which allows queryset filtering. Usage:
          {% query books author=author as mybooks %}
          {% for book in mybooks %}
            ...
          {% endfor %}
    """
    return qs.filter(**kwargs)
Respondeu 23/12/2012 em 13:27
fonte usuário

votos
6

A outra opção é que se você tiver um filtro que você quer sempre aplicada, para adicionar um gerenciador customizado no modelo em questão, que se aplica sempre o filtro para os resultados retornados.

Um bom exemplo disto é um Eventmodelo, onde por 90% das consultas que você faz do modelo que você vai querer algo como Event.objects.filter(date__gte=now), ou seja, você está normalmente interessado em Eventsque estão próximos. Isso seria algo como:

class EventManager(models.Manager):
    def get_query_set(self):
        now = datetime.now()
        return super(EventManager,self).get_query_set().filter(date__gte=now)

E no modelo:

class Event(models.Model):
    ...
    objects = EventManager()

Mas, novamente, isto aplica-se o mesmo filtro contra todas as consultas padrão feitos no Eventmodelo e por isso não é tão flexível algumas das técnicas descritas acima.

Respondeu 10/09/2012 em 12:37
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more