Necesito realizar una consulta filtrada desde dentro de una plantilla de django, para obtener un conjunto de objetos equivalente 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 averiguar cómo escribir FILTER.
Solo agrego 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 %}
fuente
'for' statements should use the format 'for x in y': for p in r | people_in_roll_department:d
. ¿Algunas ideas?Me encuentro con este problema de forma regular y, a menudo, utilizo la solución "agregar un método". Sin embargo, definitivamente hay casos en los que "agregar un método" o "calcularlo en la vista" no funcionan (o no funcionan bien). Por ejemplo, cuando está almacenando en caché fragmentos de plantilla y necesita algún cálculo de base de datos no trivial para producirlo. No desea hacer el trabajo de la base de datos a menos que sea necesario, pero no sabrá si es necesario hasta que esté profundamente en la lógica de la plantilla.
Algunas otras posibles soluciones:
Utilice la etiqueta de plantilla {% expr <expression> como <var_name>%} que se encuentra 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.
Cambia tu procesador de plantillas. Jinja2 ( http://jinja.pocoo.org/2/ ) tiene una sintaxis que es casi idéntica a la del lenguaje de plantilla de Django, pero con toda la potencia de Python disponible. También es más rápido. Esto se puede hacer al por mayor, o podría limitar su uso a las plantillas que se está trabajando, pero el uso de plantillas "más seguros" de Django para las páginas de diseño-mantenido.
fuente
La otra opción es que si tiene un filtro que siempre desea aplicar, agregue 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
Event
modelo, donde para el 90% de las consultas que haces en el modelo vas a querer algo comoEvent.objects.filter(date__gte=now)
, es decir, normalmente estás interesado enEvents
las próximas. 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 a todas las consultas predeterminadas realizadas en el
Event
modelo y, por lo tanto, algunas de las técnicas descritas anteriormente no son tan flexibles.fuente
Esto se puede solucionar 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)
fuente
Para cualquiera que busque una respuesta en 2020. Esto funcionó para mí.
En Vistas:
class InstancesView(generic.ListView): model = AlarmInstance context_object_name = 'settings_context' queryset = Group.objects.all() template_name = 'insta_list.html' @register.filter def filter_unknown(self, aVal): result = aVal.filter(is_known=False) return result @register.filter def filter_known(self, aVal): result = aVal.filter(is_known=True) return result
En plantilla:
{% for instance in alarm.qar_alarm_instances|filter_unknown:alarm.qar_alarm_instances %}
En pseudocódigo:
For each in model.child_object|view_filter:filter_arg
Espero que ayude.
fuente