Pergunta

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.

Foi útil?

Solução

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. Filtrando modelos é a lógica de dados, e produzir 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.

Outras dicas

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 %}

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 como %} tag modelo encontrado em http://www.djangosnippets.org/snippets/9/ A expressão é qualquer expressão legal Python com contexto do seu modelo como o seu âmbito local.

  2. Mude o seu processador de modelo. Jinja2 ( http://jinja.pocoo.org/2/ ) tem uma sintaxe que é quase idêntico ao a linguagem de template Django, mas com potência total Python 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 do Django "mais seguro" para as páginas manteve-designer.

Isso pode ser resolvido com uma tag 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)

A outra opção é que se você tiver um filtro que você sempre deseja aplicar, para adicionar um gerente personalizado no modelo em questão, que se aplica sempre o filtro para os resultados retornados.

Um bom exemplo disso é um modelo Event, 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 Events que estão próximo. Isso seria parecido com:

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 feito no modelo Event e por isso não é como alguns flexível das técnicas descritas acima.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top