Komentarze w Django - wspólny szablon
Używając Django, mamy dostęp do użytecznej aplikacji komentarzy - django.contrib.comments
. Pozwala ona powiązać system komentowania z różnymi modelami, w efekcie tę samą aplikację wykorzystamy umożliwiając komentowanie artykułów na blogu, zdjęć w galerii itp. Kilka znaczników pozwala w łatwy sposób osadzić widok komentarzy w szablonie. Często jednak w kilku aplikacjach sekcja komentarzy wygląda tak samo - mamy listę ostatnio dodanych wpisów i formularz pozwalający na dodanie nowej wypowiedzi. Co zrobić, żeby uniknąć kopiowania i wklejania kodu szablonu?
"Problem" wygląda następująco: załóżmy, że mamy 2 aplikacje - blog i galerię zdjęć (wygląda znajomo? ;-) ) W każdej z nich chcemy pozwolić użytkownikom na komentowanie obiektów (artykułów/zdjęć). Nic prostszego, dołączamy django.contrib.comments
do zainstalowanych aplikacji, po czym w szablonie widoku artykułu wstawiamy np. taki fragment:
{% get_comment_list for article as comment_list %} <ol> {% for comment in comment_list %} <li> <h4>{{ comment.user_name }} ({{ comment.submit_date }})</h4> <p>{{ comment.comment }}</p> </li> {% endfor %} </ol> <h3>Dodaj komentarz</h3> {% render_comment_form for article %}
I świetnie, wszystko działa, teraz żeby umożliwić komentowanie zdjęć, do szablonu galerii dodajemy podobny kod, z tą różnicą że zamiast article
pojawi się zapewne photo
czy jak tam sobie nazwiemy zmienną kontekstu. Jednak jeśli w obu wypadkach komentarze mają wyglądać na stronie tak samo, to miło by było uniknąć duplikacji kodu różniącego się tylko tym drobnym szczegółem. W takim razie radośnie wydzielamy powyższy kod do osobnego szablonu i... No właśnie - w jednym szablonie kluczowym obiektem jest article
, w drugim photo
, a szablon komentarzy chcemy mieć tylko jeden - na co się zdecydować?
Można przyjąć konwencję, że zmienną kontekstu nazwiemy obj
i przekażemy taką nazwę z widoku, np.
def read_article(request, id): # coś w stylu: article = get_object_or_404(...) return render_to_response('blog/article.html', {'obj': article})
W widoku prezentującym zdjęcie zrobimy podobnie, a w komentarzach będziemy się odwoływać do obiektu przez {% get_comment_list for obj as comment_list %}
. Będzie to działać, ale ładniej by było, gdyby zmienna była dostępna w szablonie pod nazwą mówiącą coś więcej. Na ratunek przychodzi nam znacznik {% with %}
. Do szablonu przekazujemy dane pod jakąś sensowną nazwą, a w miejscu, gdzie chcemy dołączyć komentarze, wykorzystamy ten znacznik w celu utworzenia aliasu do zmiennej.
{% with article as obj %}{% include "comments_section.html" %}{% endwith %}
A w galerii:
{% with photo as obj %}{% include "comments_section.html" %}{% endwith %}
Gotowe, wykonaliśmy ostatni krok w kierunku maksymalnego uogólnienia systemu komentarzy. Oczywiście ma to sens tylko w przypadku, gdy chcemy mieć identycznie wyglądające sekcje komentarzy w różnych miejscach witryny.