Właśnie zrobiłem moją pierwszą małą aplikację internetową w django i bardzo mi się podoba. Zaraz zacznę od konwersji starej produkcyjnej strony PHP do django i jako część jej szablonu, jest tam pasek nawigacji.
W PHP sprawdzam adres URL każdej opcji nawigacyjnej z bieżącym adresem URL, w kodzie szablonu i stosuję klasę CSS, jeśli się zgadzają. Jest przerażająco brudny.
Czy jest coś lepszego dla django lub dobry sposób obsługi kodu w szablonie?
Na początek, jak mam się zabrać do uzyskania aktualnego adresu URL?
django
navigation
Oli
źródło
źródło
<a href="{% url "view:name" %}" {% active_class "view:name" %}>
. Opcjonalnie można go używać do generowania tylko na" active"
wartość (przekazującFalse
jako drugi argument do znacznika) do dołączania do istniejącego atrybutu klasy, ale dla większości linków nav że przykładem jest to, co używam.Odpowiedzi:
Korzystam z dziedziczenia szablonów, aby dostosować nawigację. Na przykład:
base.html
about.html
źródło
<ul id="nav">....</ul>
do innego pliku, powiedzmy tabs.html. Więc teraz base.html zawierał,{%block nav%}{%include "tabs.html"%}{%endblock%}
a następnie podświetlanie aktywnej karty przestało działać (w about.html powyżej). Czy coś mi brakuje?include
działa tag. Zapoznaj się z notatką zawartą w dokumentach: docs.djangoproject.com/en/dev/ref/templates/builtins/#include W twoim przypadku, zanim spróbujesz zastąpić szablon podstawowy wabout.html
, myślę, że ma już wyrenderowany blok HTML, a nie blok szablonu Django czekający na przetworzenie.Nie potrzebujesz, aby to zrobić, spójrz na poniższy kod:
tags.py
urls.py
base.html
Otóż to. szczegóły implementacji znajdziesz na:
gnuvince.wordpress.com
110j.wordpress.com
źródło
django.core.context_processors.request
do swojegoTEMPLATE_CONTEXT_PROCESSORS
insettings.py
mysite.com
(Jako dom) orazmysite.com/blog
, ponieważ ścieżka będzie wyświetlana jako/
i/blog/
(odpowiednio), za każdym razem dając dopasowanie do poprzedniego. Jeśli nie używasz/
jako lądowania, może to być w porządku, w przeciwnym razie po prostu używamreturn 'active' if pattern == request.path else ''
(nie widziałem jeszcze problemów z tym, ale właśnie skonfigurowałem, używając tego).Podobała mi się czystość 110j powyżej, więc wziąłem jej większość i refaktoryzowałem, aby rozwiązać 3 problemy, które miałem z nią:
Oto ona:
tags.py:
urls.py:
base.html:
źródło
Jestem autorem linii django, którą napisałem specjalnie, aby rozwiązać to pytanie: D
Denerwowało mnie stosowanie (całkowicie akceptowalnej) metody jpwatts we własnych projektach i zaczerpnąłem inspirację z odpowiedzi 110j. Rodowód wygląda następująco:
ancestor
jest po prostu zastępowany przez „aktywny”, jeśli argument jest zgodny z początkiem adresu URL bieżącej strony.{% url %}
Obsługiwane są również zmienne argumenty i odwrotna rozdzielczość pełnego typu. Wrzuciłem kilka opcji konfiguracyjnych, trochę go dopracowałem i zapakowałem, aby wszyscy mogli z niego korzystać.Jeśli ktoś jest zainteresowany, przeczytaj więcej na ten temat pod adresem:
>> github.com/marcuswhybrow/django-lineage
źródło
Od Django 1.5 :
Więc jeśli korzystasz z takich widoków, możesz dodać coś podobnego
breadcrumbs
jako pole na poziomie klasy i użyć go w swoich szablonach.Przykładowy kod widoku:
W swoim szablonie możesz to wykorzystać w ten sposób:
Jeśli chcesz dodatkowo „podświetlić” nadrzędne elementy nawigacji, musisz rozszerzyć
breadcrumbs
listę:... aw Twoim szablonie:
Jest to łatwe i przejrzyste rozwiązanie, które działa całkiem dobrze z nawigacją zagnieżdżoną.
źródło
.active
?breadcrumbs
Jeśli chcesz, możesz oczywiście włożyć jeden przedmiot . Ale masz rację - mój przykład nie jest najlepszy.Możesz zastosować klasę lub identyfikator do elementu body strony zamiast do określonego elementu nawigacyjnego.
HTML:
CSS:
źródło
Robię to tak:
a potem wszystko, co muszę zrobić, to dodać
{'active_tab': 'statistics'}
do mojego słownika kontekstowego.Jeśli używasz
RequestContext
, możesz pobrać aktualną ścieżkę w swoim szablonie jako:Twoim zdaniem:
źródło
Wziąłem kod z nivhab powyżej i usunąłem trochę dziwności i przekształciłem go w czysty szablon szablonu, zmodyfikowałem go tak, aby / account / edit / nadal aktywował / account / tab.
źródło
To tylko wariant rozwiązania CSS zaproponowanego przez Toba powyżej:
Uwzględnij następujące elementy w swoim szablonie podstawowym:
Następnie w twoich szablonach, które rozszerzają podstawowe użycie:
Następnie możesz użyć css, aby podświetlić bieżący obszar na podstawie tagu body (na przykład jeśli mamy link z identyfikatorem nav-home):
źródło
Możesz użyć funkcji reverse z odpowiednimi parametrami, aby uzyskać aktualny adres URL.
źródło
Dzięki za dotychczasowe odpowiedzi panowie. Znowu poszedłem na coś nieco innego ...
W moim szablonie:
Po ustaleniu, na której stronie jestem w logice (zwykle w urls.py), przekazuję
class="selected"
jako część kontekstu pod odpowiednią nazwą do szablonu.Np. Jeśli jestem na stronie link1, dołączę
{'link1_active':' class="selected"'}
do kontekstu, aby szablon zgarnął i wstrzyknął.Wygląda na to, że działa i jest dość czysty.
Edycja: aby zachować HTML poza moim kontrolerem / widokiem, zmodyfikowałem to trochę:
To sprawia, że szablon jest trochę mniej czytelny, ale zgadzam się, lepiej nie przepychać surowego kodu HTML z pliku URL.
źródło
Mam wiele menu na tej samej stronie, które są tworzone dynamicznie za pomocą pętli. Powyższe posty odnoszące się do kontekstu dały mi szybką poprawkę. Mam nadzieję, że to komuś pomoże. (Używam tego oprócz aktywnego tagu szablonu - moja poprawka rozwiązuje problem dynamiczny). Wydaje się, że to głupie porównanie, ale działa. Zdecydowałem się nazwać zmienne active_something-unique i something-unique, w ten sposób działa to z zagnieżdżonymi menu.
Oto fragment widoku (wystarczający, aby zrozumieć, co robię):
A to z szablonu:
źródło
Moim rozwiązaniem było napisanie prostego procesora kontekstu do ustawiania zmiennej na podstawie ścieżki żądania:
(Nie zapomnij dodać własnego procesora do TEMPLATE_CONTEXT_PROCESSORS w settings.py).
Następnie w szablonie podstawowym używam tagu ifequal dla każdego linku, aby określić, czy dołączyć klasę „aktywną”. To prawda, że to podejście jest ściśle ograniczone do elastyczności struktury ścieżki, ale działa w przypadku mojego stosunkowo skromnego wdrożenia.
źródło
Chciałem tylko udostępnić moje drobne ulepszenia w poście nivhab. W mojej aplikacji mam subnavigacje i nie chciałem ich ukrywać używając tylko CSS, więc potrzebowałem jakiegoś tagu "if", aby wyświetlić subnavigację dla elementu, czy nie.
Możesz tego używać w zasadzie w taki sam sposób, jak aktywnego tagu:
źródło
Kolejne ulepszenie oryginalnego rozwiązania.
Akceptuje wiele wzorców i najlepiej sprawdza się również wzorce nienazwane zapisane jako względny adres URL zawinięty w „” ”, na przykład:
Tag wygląda tak:
źródło
Użyłem jquery do wyróżnienia moich navbarów. To rozwiązanie po prostu dodaje klasę css „active” do pozycji, która pasuje do selektora css.
źródło
Trochę ulepszenia w stosunku do odpowiedzi @tback , bez żadnych
%if%
tagów:Użyj go w swoim szablonie w ten sposób:
I uwzględnij
"django.core.context_processors.request"
w swoimTEMPLATE_CONTEXT_PROCESSORS
otoczeniu.źródło
Uważam, że najlepiej jest użyć tagu włączenia:
templates/fnf/nav_item.html
To jest tylko mój podstawowy element nawigacyjny bootstrap, który chcę renderować.
Pobiera wartość href i opcjonalnie wartość link_name.
is_active
jest obliczany na podstawie bieżącego żądania.templatetags/nav.py
Następnie użyj go w nawigacji:
templates/fnf/nav.html
źródło
/about/company-history/
lub/about/what-we-do/
is_active
można je wymienić, a inne klucze dodać do słownika. Również czek może byćcontext.request.resolver_match.url_name.startswith(x)
lub cokolwiek innego. Możesz również mieć kod przed instrukcją return, aby ustalić wartości dict. Możesz także użyć różnych szablonów, np. Jednegotop_level_nav.html
z inną logiką itp.Nieznacznie modyfikując odpowiedź Andreasa, wygląda na to, że możesz przekazać nazwę trasy z urls.py do tagu szablonu. W moim przykładzie
my_tasks
, a następnie w funkcji znacznika szablonu użyj funkcji odwrotnej, aby ustalić, jaki powinien być adres URL, wtedy możesz dopasować go do adresu URL w obiekcie żądania (dostępne w kontekście szablonu)urls.py
template.html
źródło
Wiem, że spóźniłem się na przyjęcie. Nie podobało mi się jednak żadne z popularnych rozwiązań:
Metoda blokowa wydaje się błędna: myślę, że nawigacja powinna być samodzielna.
Metoda template_tag wydaje się nieprawidłowa: nie podoba mi się to, że muszę najpierw pobrać adres URL z tagu url. Myślę też, że klasę css należy zdefiniować w szablonie, a nie w tagu.
Dlatego napisałem filtr, który nie ma wad, które opisałem powyżej. Zwraca,
True
jeśli adres URL jest aktywny i dlatego może być używany z{% if %}
:Kod:
Po prostu upewnij się, że używasz
RequestContext
na stronach z nawigacją lub włączasz żądanie context_processor w swoimsettings.py
źródło
Widziałem jpwatts , 110j , nivhab i Marcus Whybrow , ale wydaje się, że wszystkim im czegoś brakuje: a co ze ścieżką ? Dlaczego jest zawsze aktywny?
Zrobiłem więc inny sposób, łatwiejszy, który sprawia, że „kontroler” sam decyduje i myślę, że rozwiązuje większość dużych problemów.
Oto mój niestandardowy tag:
Następnie "kontroler" deklaruje potrzebne klasy CSS (tak naprawdę najważniejsze to deklaruje swoją obecność do szablonu)
Na koniec renderuję go na pasku nawigacyjnym:
Tak więc każda strona ma własną
nav_css_class
wartość do ustawienia, a jeśli jest ustawiona, szablon renderuje się jako aktywny: bez potrzebyrequest
w kontekście szablonu, bez parowania adresów URL i żadnych problemów ze stronami z wieloma adresami URL lub stroną główną.źródło
Zainspirowany tym rozwiązaniem zacząłem stosować takie podejście:
źródło
Oto moja propozycja. Skończyło się na zaimplementowaniu klasy w moich widokach, która zawiera moją strukturę nawigacji (płaska z niektórymi metadanymi). Następnie wstrzykuję to do szablonu i renderuję.
Moje rozwiązanie dotyczy i18n. Prawdopodobnie powinien być nieco bardziej abstrakcyjny, ale tak naprawdę nie przejmowałem się tym.
views.py:
Zdefiniowałem logikę szablonu przy użyciu takich elementów. Szablon podstawowy:
Rzeczywiste uwzględnienie (obejmuje / navigation.html):
Miejmy nadzieję, że ktoś uzna to za przydatne! Myślę, że byłoby całkiem łatwo rozszerzyć ten pomysł na obsługę zagnieżdżonych hierarchii itp.
źródło
Utwórz szablon dołączania „intranet / nav_item.html”:
I umieść to w elemencie nav:
I musisz to dodać do ustawień:
źródło
tutaj jest całkiem proste rozwiązanie, https://github.com/hellysmile/django-activeurl
źródło
z tego pytania SO
W razie potrzeby powtórz te czynności dla każdego łącza.
źródło
/blog/posts/2021/04/12
byłby adresem URL, element / blog / nav byłby aktywny.Questions
,Tags
,Users
,Badges
,Unanswered
,Ask Question
. to nie zadziałaQuestions
, ale dla wszystkich innych nawigacji będzie działać dobrze.Użyłem również jQuery, aby go podświetlić i uważam, że jest bardziej elegancki niż zaśmiecanie szablonu niesemantycznymi tagami szablonu Django.
Poniższy kod działa z zagnieżdżonymi listami rozwijanymi w bootstrap 3 (podświetla zarówno element nadrzędny, jak i podrzędny
<li>
.Dość łatwo jest również dodać
click
zdarzeniereturn false
(lub zmienićhref
atrybut na#
) dla bieżącej strony, bez zmiany znaczników template / html:źródło
Używam kombinacji tej mieszanki do widoków opartych na klasach:
z tym w szablonie:
źródło
Moje jest trochę podobne do innego podejścia JS przesłanego wcześniej ... tylko bez jQuery ...
Powiedzmy, że w base.html mamy co następuje:
Właśnie utworzyłem hierarchię tak, aby podążała za określonym wzorcem adresu URL ... po adresie hosta ... mam swoją główną kategorię, np. Dom, wiadomości, analiza itp., A wyrażenie regularne po prostu wyciąga pierwsze słowo z lokalizacji
źródło