Pregunta

Necesito realizar una consulta filtrada desde una plantilla de django, para obtener un conjunto de objetos equivalentes al código de Python dentro de una vista:

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

En mi plantilla me gustaría hacer

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

pero parece que no puedo encontrar la manera de escribir FILTER.

¿Fue útil?

Solución

No puedes hacer esto, que es por diseño. Los autores del marco Django pretendían una separación estricta del código de presentación de la lógica de datos. Filtrar modelos es lógica de datos y generar HTML es lógica de presentación.

Entonces tienes varias opciones. Lo más fácil es hacer el filtrado, luego pasar el resultado a render_to_response. O podría escribir un método en su modelo para poder decir {% for object in data.filtered_set %}. Finalmente, puede escribir su propia etiqueta de plantilla, aunque en este caso específico le aconsejaría que no.

Otros consejos

Acabo de agregar una etiqueta de plantilla adicional como esta:

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

Entonces puedo hacer:

{% for category in categories %}
  {% for thing in things|in_category:category %}
    {{ thing }}
  {% endfor %}
{% endfor %}

Me encuentro con este problema de forma regular y a menudo uso " agregue un método " solución. Sin embargo, definitivamente hay casos en los que & Quot; agregue un método & Quot; o " calcularlo en la vista " no funciona (o no funciona bien). P.ej. cuando está almacenando en caché fragmentos de plantilla y necesita algún cálculo de DB no trivial para producirlo No desea hacer el trabajo de base de datos a menos que lo necesite, pero no sabrá si es necesario hasta que esté inmerso en la lógica de la plantilla.

Algunas otras posibles soluciones:

  1. Utilice la {% expr < expresión > como < var_name > %} etiqueta de plantilla encontrada en http://www.djangosnippets.org/snippets/9/ La expresión es cualquier expresión legal de Python con el contexto de su plantilla como su ámbito local.

  2. Cambie su procesador de plantillas. Jinja2 ( http://jinja.pocoo.org/2/ ) tiene una sintaxis casi idéntica a el lenguaje de plantilla de Django, pero con el poder completo de Python disponible. También es más rápido. Puede hacerlo al por mayor, o puede limitar su uso a plantillas en las que usted está trabajando, pero use Django's & Quot; más seguro & Quot; plantillas para páginas mantenidas por diseñadores.

Esto se puede resolver con una etiqueta de asignación:

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)

La otra opción es que si tiene un filtro que siempre desea aplicar, agregar un administrador personalizado en el modelo en cuestión que siempre aplica el filtro a los resultados devueltos.

Un buen ejemplo de esto es un modelo Event, donde para el 90% de las consultas que haces sobre el modelo vas a querer algo como Event.objects.filter(date__gte=now), es decir, normalmente estás interesado en Events que son próxima Esto se vería así:

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

Y en el modelo:

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

Pero de nuevo, esto aplica el mismo filtro contra todas las consultas predeterminadas realizadas en el modelo <=> y, por lo tanto, no es tan flexible como algunas de las técnicas descritas anteriormente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top