2011-08-22 21 views
6

¿Hay alguna manera de hacerlo isinstance/issubclass en una plantilla de Django? Me doy cuenta de que puedo escribir mi propia plantilla, pero me sorprende que esto no sea posible, lo que me hace pensar que estoy haciendo algo mal o me falta algo obvio.IsInstance en la plantilla de Django?

Deseo mostrar dos segmentos diferentes de marcado, dependiendo del tipo de elemento que estoy mostrando mientras iterativo sobre mi colección. ¡Gracias!

Respuesta

5

Si todos estos heredan de un tipo de base común, pero necesita saber de qué tipo es, puede implementar un método en la base que devuelve el tipo - luego puede llamar al if foo.get_type == 'type1' (o lo que sea) en tu plantilla

0

Le falta algo aquí: la única lógica en la plantilla se supone que maneja la representación de la plantilla. isinstance/issubclass huele claramente como lógica de vista, y debería estar en la vista. Si la prestación de plantilla depende de esas funciones (que supongo que sí), se debe aplicar la lógica en la vista, y sólo tiene que pasar la plantilla lo que necesita saber:

# in the view: 
if isinstance(some_obj, SomeClass): 
    do_fancy_template_stuff = True 
else: 
    do_fancy_template_stuff = False 

# in the template: 
{% if do_fancy_template_stuff %} 
    <fancy_template_stuff /> 
{% endif %} 

Recuerde: el motor Django plantillas era creado teniendo en mente a los no programadores, como los diseñadores.

+4

Hmmm, estoy de acuerdo con el sentimiento en general, pero no estoy tan seguro de llegar tan lejos como esto. Mi caso de uso es que tengo una colección de elementos, todos de tipo base común, pero mezclados dentro de la colección. Un foo debería mostrarse así, una barra debería mostrar así, de forma similar, pero ligeramente diferente. Tienen campos ligeramente diferentes para mostrar, de ahí los diferentes fragmentos de visualización, por lo que es tentador decir {% if item.field_that_bars_have%} o similar, pero eso parece desagradable. – Ludo

+0

Supongo que la forma correcta de manejar esto es crear una etiqueta personalizada, render_result_item, o algo que pueda seleccionar el fragmento de visualización correcto. De esta forma, la lógica permanece fuera de la plantilla de visualización, aunque a expensas de colocarla en algún lugar, nuestro programador/diseñador no podrá encontrarla. O podría escribir una etiqueta de plantilla de instancia. O podría agregar un get_type o algo al modelo. Estoy divagando ahora, gracias por su respuesta :). – Ludo

8

Creo que un simple filtro de plantilla aquí se ajusta mejor. Es realmente rápido de implementar y fácil de llamar. Algo como esto:

en templatetags/my_filters.py:

from django import template 
from django.utils.importlib import import_module 

register = template.Library() 

@register.filter 
def isinst(value, class_str): 
    split = class_str.split('.') 
    return isinstance(value, getattr(import_module('.'.join(split[:-1])), split[-1])) 

en su plantilla:

{% load my_filters %} 

... 

{% if myvar|isinst:"mymodule.MyClass" %} 
...do your stuff 
{% endif %} 

A pesar de lo anterior es un ejemplo de código (no probado), I Creo que debería funcionar. Para obtener más información sobre los filtros de plantillas personalizadas favor ver the django documentation

EDIT: editó la respuesta a demostrar que el argumento del filtro es en realidad una cadena y no una clase de Python

+0

Tener que hacer referencia a la ruta completa de un modelo hace que esta solución sea frágil para las refactorizaciones en el backend, además requiere que el diseñador de plantillas/html conozca estas rutas. No es la mejor manera de hacerlo si su equipo está dividido en programadores back-end y diseñadores de plantillas. –

+0

Estoy totalmente de acuerdo.La intención aquí es responder la pregunta; esto claramente no es la mejor práctica para hacer cosas condicionales en sus plantillas. – ppetrid