Pisanie pierwszej aplikacji Django, część 7.¶
Ten tutorial zaczyna się, gdzie został przerwany Tutorial 6 </intro/tutorial06>. Kontynuujemy tworzenie aplikacji internetowych ankiet i skupimy się na dostosowaniu do naszych potrzeb automatycznie wygenerowanego panelu administracyjnego Django, który pierwotnie odkrywaliśmy w Tutorialu 2 </intro/tutorial02>.
Dostosuj formularz panelu administracyjnego¶
Rejestrując model Question
przez admin.site.register(Question)
, umożliwiłeś Django skonstruować domyślną reprezentację formularza. Często będziesz chciał zmienić jak formularz panelu administracyjnego wygląda i działa. Będziesz to robił mówiąc Django, jakie wybierasz opcje, rejestrując obiekt.
Zobaczmy jak to działa zmieniając kolejność pól w formularzu edycji. Zamień linię admin.site.register(Question)
na:
from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
fields = ['pub_date', 'question_text']
admin.site.register(Question, QuestionAdmin)
Będziesz realizował ten wzorzec stworzenie klasy model admin, następnie przekazanie jej jako drugiego argumentu do admin.site.register()
– w dowolnym momencie, kiedy potrzebujesz zmienić opcje admina dla modelu.
Konkretnie ta zmiana powyżej powoduje, że „Publication date” jest przed polem „Question”:
Nie robi to wrażenia z tylko dwoma polami, ale dla formularzy admina z tuzinami pól, wybranie intuicyjnego porządku jest ważnym szczegółem użyteczności.
A mówiąc o formularzach z tuzinami pól, możesz chcieć podzielić formularz na fieldsety:
from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date']}),
]
admin.site.register(Question, QuestionAdmin)
Pierwszym elementem każdej krotki w fieldsets
jest tytuł fieldsetu. Tak wygląda teraz nasz formularz:
Dostosuj widok listy panelu administracyjnego¶
Teraz, kiedy strona admina dla pytania wygląda dobrze, poprawmy nieco stronę „change list” – tę, która wyświetla wszystkie pytania w systemie.
Tak ona wygląda w tym momencie:
Domyślnie Django wyświetla str()
każdego obiektu. Ale czasem bardziej pomocne byłoby wyświetlanie poszczególnych pól. Aby to zrobić, użyj list_display
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date')
Na wszelki wypadek dodajmy też metodę was_published_recently()
z Tutoriala 2:
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date', 'was_published_recently')
Teraz strona „change list” pytań wygląda w ten sposób:
Możesz klikać w nagłówki kolumn, aby sortować po tych wartościach – z wyjątkiem przypadku nagłówka was_published_recently
, ponieważ sortowanie po wyniku arbitralnej metody nie jest wspierane. Zwróć też uwagę, że nagłówek kolumny dla was_published_recently
jest domyślnie nazwą metody (z podkreślnikami zamienionymi na spacje) i każda linia zawiera reprezentację w ciągu znaków wyniku.
Możesz to poprawić dając tej metodzie (w polls/models.py
) kilka atrybutów, w następujący sposób:
class Question(models.Model):
# ...
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
Po więcej informacji na temat tych właściwości metod, zobacz list_display
.
Zmień znów swój plik polls/admin.py
i dodaj ulepszenie do strony „change list” Questions
: filtry, z użyciem list_filter
. Dodaj następującą linię do QuestionAdmin
:
list_filter = ['pub_date']
Doda to sidebar „Filter”, który pozwala ludziom filtrować listę obiektów używając pola pub_date
:
Typ wyświetlanego filtru zależy od typu pola, po którym filtrujesz. Ponieważ pub_date
to DateTimeField
, Django wie, aby dać odpowiednie opcje w filtrze: „Any date”, „Today”, „Past 7 days”, „This month”, „This year”.
Dobrze się to zarysowuje. Dodajmy trochę możliwości wyszukiwania:
search_fields = ['question_text']
To dodaje pole wyszukiwania na górze „change listy”. Kiedy ktoś wprowadzi wyrażenie wyszukiwania, Django przeszuka pole question_text
. Możesz użyć tyle pól, na ile masz ochotę – choć z powodu, że pod maską użyje to zapytania LIKE
, ograniczenie liczby pól wyszukiwania do rozsądnej liczby ułatwi twojej bazie danych wykonać wyszukiwanie.
Teraz jest dobry moment, by zwrócić uwagę, że „change lista” daje ci wolną paginację. Domyślnie wyświetla ona 100 elementów na stronę. Zmień paginację listy
, pola wyszukiwania
, filtry
, hierarchie dat
i:attr:kolejność kolumn nagłówków <django.contrib.admin.ModelAdmin.list_display> tak, aby wspólnie współgrały tak, jak uważasz, że powinny.
Dostosuj wygląd i pracę z panelem administracyjnym¶
Oczywiście, wyświetlanie napisu „Django administration” na górze każdej strony panelu administracyjnego jest bez sensu. To tylko tekst zastępczy.
To proste do zmiany przy użyciu systemu szablonów Django. Panel administracyjny Django jest napędzany przez samo Django i jego interfejsy używają własnego systemu szablonów Django.
Dostosowywanie szablonów twojego projektu¶
Stwórz katalog templates
w katalogu twojego projektu (tym, który zawiera manage.py
). Szablony mogą być składowane w dowolnym miejscu twojego systemu plików, do którego może mieć dostęp Django. (Django jest uruchomione na tym samym użytkowniku co serwer.) Jednakże trzymanie szablonów wewnątrz projektu jest dobrą konwencją.
Otwórz swój plik ustawiń (mysite/settings.py
, pamiętaj) i dodaj opcję DIRS
w ustawieniu TEMPLATES
:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
DIRS
jest listą katalogów systemu plików, które należy sprawdzić ładując szablony Django; jest ścieżką wyszukiwania.
Organizacja szablonów
Tak samo jak pliki statyczne, moglibyśmy mieć wszystkie nasze szablony razem, w jednym dużym katalogu na szablony i mogłoby to całkowicie dobrze działać. Jednakże szablony, które należą do poszczególnej aplikacji powinny być umieszczane raczej w katalogu szablonów tej aplikacji (np. polls/templates
) niż w katalogu szablonów projektu (templates
). Omówimy bardziej szczegółowo w ``tutorialu aplikacji wielokrotnego użytku </intro/reusable-apps>` dlaczego to robimy.
Teraz stwórz katalog o nazwie admin
wewnątrz templates
i skopiuj szablon admin/base_site.html
z katalogu domyślnych szablonów panelu administracyjnego z kodu źródłowego Django (django/contrib/admin/templates
) do tego katalogu.
Gdzie są pliki źródłowe Django?
Jeśli masz trudność w odnalezieniu miejsca, gdzie są zlokalizowane pliki źródłowe Django w twoim systemie, uruchom następujące polecenie:
$ python -c "import django; print(django.__path__)"
Następnie po prostu zmień plik i zamień {{ site_header|default:_('Django administration') }}
(wliczając nawiasy klamrowe) na nazwę swojej strony, która będzie pasować. Powinieneś skończyć z sekcją kodu typu:
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}
Używamy tego podejścia, aby nauczyć cię jak nadpisywać szablony. W prawdziwym projekcie, prawdopodobnie użyłbyś atrybutu django.contrib.admin.AdminSite.site_header
, aby w prostszy sposób zrobić tę konkretną zmianę.
Ten plik szablonu zawiera pełno tekstów typu {% block branding %}
i {{ title }}
. Tagi {%
i {{
są częścią języka szablonów Django. Kiedy Django renderuje admin/base_site.html
, ten język szablonów jest ewaluowany i produkuje ostateczną stronę HTML, tak jak widzieliśmy w Tutorialu 3.
Zwróć uwagę, że każdy domyślny szablon panelu administracyjnego Django może być nadpisany. Aby nadpisać szablon, po prostu zrób tę samą czynność, którą zrobiłeś z base_site.html
– skopiuj je z domyślnego katalogu do swojego własnego katalogu i zrób zmiany.
Zmiana szablonów twojej aplikacji
¶
Bystrzy czytelnicy zapytają: Ale skoro DIRS
było domyślnie puste, jak Django odnajdywało domyślne szablony admina? Odpowiedzią jest, tak długo jak APP_DIRS
jest ustawione na True
, Django automatycznie szuka podkatalogu templates/
w każdym pakiecie aplikacji, aby użyć go jako fallback (nie zapomnij, że django.contrib.admin
jest aplikacją).
Nasza aplikacja ankietowa nie jest bardzo złożona i nie potrzebuje customowych szablonów admina. Lecz gdyby urosła do bardziej skomplikowanej i wymagała modyfikacji standardowych szablonów admina do jakiś swoich funkcjonalności, byłoby bardziej rozsądne modyfikować szablony aplikacji niż te w projekcie. W ten sposób mógłbyś zawrzeć aplikację ankietową w dowolnym nowym projekcie i miałbyś pewność, że odnajdzie customowe szablony, których potrzebuje.
W dokumentacji ładowania szablonów więcej informacji o tym, jak Django odnajduje swoje szablony.
Dostosuj stronę indeksu panelu administracyjnego¶
W podobnym tonie możesz chcieć zmienić wygląd i odbiór strony indeksu panelu admina Django.
Domyślnie wyświetla ona wszystkie aplikacje w INSTALLED_APPS
, które zostały zarejestrowane z aplikacją admin, w kolejności alfabetycznej. Możesz chcieć dokonać istotnych zmian w wyglądzie. W końcu, strona główna jest prawdopodobnie najważniejszą stroną admina i powinna być łatwa w użyciu.
Szablon do dostosowania to admin/index.html
. (Zrób to samo co z admin/base_site.html
w poprzedniej sekcji – skopiuj go z domyślnego katalogu do swojego katalogu zmienionych szablonów). Zedytuj plik. Zobaczysz, że używa on zmiennej szablonu o nazwie app_list
. Ta zmienna zawiera wyszystkie zainstalowane aplikacje Django. Zamiast jej używać możesz zahardcode’ować linki do adminowych stron obiektów w dowolny sposób, który uznasz za najlepszy.
Co następnie?¶
Tutorial dla początkujących kończy się tutaj. W międzyczasie możesz chcieć sprawdzić niektóre z kierunków wskazanych w gdzie iść dalej.
Jeśli jesteś zaznajomiony z pakietowaniem w Pythonie i zainteresowany jak uczynić ankiety „aplikacją reusable”, sprawdź Zaawansowany tutorial: Jak pisać aplikacje do ponownego wykorzystania.