2011-08-22 15 views
6

Czy istnieje sposób zrobić isinstance/issubclass w szablonie Django? Zdaję sobie sprawę, że mogę napisać własny templatetag, ale jestem zaskoczony, że to nie jest możliwe, co powoduje, że myślę, że albo robię coś źle, albo brakuje mi czegoś oczywistego.IsInstance w szablonie Django?

Chcę wyświetlić dwa różne segmenty znaczników, w zależności od tego, jaki typ elementu wyświetlam podczas iteracji nad moją kolekcją. Dzięki!

Odpowiedz

5

Jeśli wszystkie te elementy dziedziczą ze wspólnego podstawowego typu, ale musisz wiedzieć, jaki to jest, możesz po prostu zaimplementować metodę na podstawie, która zwraca typ - wtedy możesz zadzwonić pod numer if foo.get_type == 'type1' (lub cokolwiek innego) w twoim szablonie.

0

W tym miejscu brakuje czegoś: jedyna logika w szablonie ma obsługiwać renderowanie szablonu. isinstance/issubclass Wyraźnie pachnie logiką widoku i powinno być w widoku. Jeśli rendering szablonu zależy od tych funkcji (co myślę, że jest), należy realizować logikę w widoku i po prostu przekazać szablon co trzeba wiedzieć:

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

Pamiętaj: silnik Django szablonów było Stworzyłem mając na uwadze tworzenie nie-programistów, takich jak projektanci.

+4

Hmmm, zgadzam się z nastrojów w ogóle, ale nie jestem tak pewny, że posunę się aż tak daleko. Mój przypadek użycia to, mam kolekcję przedmiotów, wszystkie o typowym typie bazowym, ale mieszane w ramach kolekcji. Foo powinno być wyświetlane w ten sposób, pasek powinien wyświetlać się w ten sposób, w podobny sposób, ale nieco inaczej. Mają nieco inne pola do wyświetlenia, stąd różne fragmenty ekranu, więc warto powiedzieć, {% if item.field_that_bars_have%} lub podobnego, ale wydaje się to nieprzyjemne. – Ludo

+0

Domyślam się, że prawidłowym sposobem obsłużenia tego jest utworzenie niestandardowego znacznika, render_result_item lub czegoś, co może wybrać poprawny fragment wyświetlania. W ten sposób logika pozostaje poza szablonem widoku, chociaż kosztem umieszczenia go gdzieś, że nasz nie programista/projektant nie będzie w stanie go znaleźć. Mogę napisać szablon templatetag. Albo mogę dodać get_type lub coś do modelu. Teraz się włóczę - dzięki za odpowiedź :). – Ludo

8

Myślę, że prosty filtr szablonu pasuje najlepiej. Jest naprawdę szybki w realizacji i łatwy do wywołania. Coś takiego:

w 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])) 

w szablonie:

{% load my_filters %} 

... 

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

Chociaż powyższe jest przykładowy kod (nie testowane), I wierzę, że to powinno działać. uzyskać więcej informacji na temat niestandardowych filtrów szablonu zapoznaj the django documentation

EDIT: Zmieniano odpowiedź, aby pokazać, że argument filtr jest faktycznie ciągiem, a nie python Klasa

+0

Konieczność odwoływania się do pełnej ścieżki modelu sprawia, że ​​to rozwiązanie jest kruche do refaktoryzacji w backendie, a ponadto wymaga od projektanta szablonu/html znajomości tych ścieżek. Nie jest to najlepszy sposób, jeśli Twój zespół jest podzielony na programistów i projektantów szablonów. –

+0

Całkowicie się zgadzam.Chodzi o to, aby odpowiedzieć na pytanie; to oczywiście nie jest najlepsza praktyka do robienia warunkowych rzeczy w szablonach. – ppetrid