{"title":"Pisanie pierwszej aplikacji Django, część 7.","version":"4.1","locale":"pl","docname":"intro/tutorial07","url":"/pl/4.1/intro/tutorial07/","canonical":"https://djangodocs.dev/pl/4.1/intro/tutorial07/","summary":"This tutorial begins where Tutorial 6 left off. We’re continuing the web-poll application and will focus on customizing Django’s automatically-generated…","html":"<h1>Pisanie pierwszej aplikacji Django, część 7.<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-7\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>This tutorial begins where <a class=\"reference internal\" href=\"/pl/4.1/intro/tutorial06/\"><span class=\"doc\">Tutorial 6</span></a> left off. We’re\ncontinuing the web-poll application and will focus on customizing Django’s\nautomatically-generated admin site that we first explored in <a class=\"reference internal\" href=\"/pl/4.1/intro/tutorial02/\"><span class=\"doc\">Tutorial 2</span></a>.</p>\n<aside class=\"admonition-where-to-get-help admonition\" role=\"note\">\n<p class=\"admonition-title\">Gdzie szukać pomocy:</p>\n<p>Jeśli masz trudności w przejściu tego tutorialu, przejdź do sekcji <a class=\"reference internal\" href=\"/pl/4.1/faq/help/\"><span class=\"doc\">Uzyskiwanie pomocy</span></a> często zadawanych pytań.</p>\n</aside>\n<section id=\"customize-the-admin-form\">\n<h2>Dostosuj formularz panelu administracyjnego<a class=\"heading-anchor\" href=\"#customize-the-admin-form\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Rejestrując model <code class=\"docutils literal notranslate\">Question</code> przez <code class=\"docutils literal notranslate\">admin.site.register(Question)</code>, umożliwiłeś Django skonstruowanie domyślnej reprezentacji formularza. Często będziesz chciał zmienić to jak formularz panelu administracyjnego wygląda i działa. Będziesz to robił mówiąc Django, jakie wybierasz opcje, rejestrując obiekt.</p>\n<p>Zobaczmy jak to działa zmieniając kolejność pól w formularzu edycji. Zamień linię <code class=\"docutils literal notranslate\">admin.site.register(Question)</code> na:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/admin.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Question\n\n\n<span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">]</span>\n\nadmin<span class=\"o\">.</span>site<span class=\"o\">.</span>register<span class=\"p\">(</span>Question<span class=\"p\">,</span> QuestionAdmin<span class=\"p\">)</span>\n</code></pre></figure>\n<p>Będziesz realizował ten wzorzec  stworzenie klasy model admin, następnie przekazanie jej jako drugiego argumentu do <code class=\"docutils literal notranslate\">admin.site.register()</code> – w dowolnym momencie, kiedy potrzebujesz zmienić opcje admina dla modelu.</p>\n<p>Konkretnie ta zmiana powyżej powoduje, że „Publication date” jest przed polem „Question”:</p>\n<img alt=\"Fields have been reordered\" src=\"/pl/4.1/_images/admin07.png\" />\n<p>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.</p>\n<p>A mówiąc o formularzach z tuzinami pól, możesz chcieć podzielić formularz na fieldsety:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/admin.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Question\n\n\n<span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    fieldsets <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span>               <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">]}),</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;Date information&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">]}),</span>\n    <span class=\"p\">]</span>\n\nadmin<span class=\"o\">.</span>site<span class=\"o\">.</span>register<span class=\"p\">(</span>Question<span class=\"p\">,</span> QuestionAdmin<span class=\"p\">)</span>\n</code></pre></figure>\n<p>Pierwszym elementem każdej krotki w <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets\" title=\"django.contrib.admin.ModelAdmin.fieldsets\"><code class=\"xref py py-attr docutils literal notranslate\">fieldsets</code></a> jest tytuł fieldsetu. Tak wygląda teraz nasz formularz:</p>\n<img alt=\"Form has fieldsets now\" src=\"/pl/4.1/_images/admin08t.png\" />\n</section>\n<section id=\"adding-related-objects\">\n<h2>Dodawanie powiązanych obiektów<a class=\"heading-anchor\" href=\"#adding-related-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Ok, mamy stronę admina dla pytań, ale <code class=\"docutils literal notranslate\">Question</code> ma wiele wyborów i strona admina tych wyborów nie wyświetla.</p>\n<p>Jeszcze nie wyświetla.</p>\n<p>Są dwa sposoby rozwiązania tego problemu. Pierwszy to zarejestrować <code class=\"docutils literal notranslate\">Choice</code> z adminem tak jak zrobiliśmy przed chwilą z <code class=\"docutils literal notranslate\">Question</code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/admin.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Choice<span class=\"p\">,</span> Question\n<span class=\"c1\"># ...</span>\nadmin<span class=\"o\">.</span>site<span class=\"o\">.</span>register<span class=\"p\">(</span>Choice<span class=\"p\">)</span>\n</code></pre></figure>\n<p>Teraz „Choices” są dostępną opcją w adminie Django. Formularz „Add choice” wygląda tak:</p>\n<img alt=\"Choice admin page\" src=\"/pl/4.1/_images/admin09.png\" />\n<p>W tym formularzu pole „Question” jest polem wyboru zawierającym wszystkie pytania z bazy danych. Django wie, że <a class=\"reference internal\" href=\"/pl/4.1/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\">ForeignKey</code></a> powinno być reprezentowane w adminie jako <code class=\"docutils literal notranslate\">&lt;select&gt;</code>. W naszym przypadku istnieje tylko jedno pytanie w tym momencie.</p>\n<p>Also note the „Add another question” link next to „Question.” Every object with\na <code class=\"docutils literal notranslate\">ForeignKey</code> relationship to another gets this for free. When you click\n„Add another question”, you’ll get a popup window with the „Add question” form.\nIf you add a question in that window and click „Save”, Django will save the\nquestion to the database and dynamically add it as the selected choice on the\n„Add choice” form you’re looking at.</p>\n<p>Ale tak naprawdę to niewydajny sposób na dodawanie obiektów <code class=\"docutils literal notranslate\">Choice</code> do systemu. Byłoby lepiej, jeśli mógłbyś dodać zestaw wyborów bezpośrednio, gdy tworzysz obiekt <code class=\"docutils literal notranslate\">Question</code>. Zróbmy tak.</p>\n<p>Usuń wywołanie <code class=\"docutils literal notranslate\">register()</code> dla modelu <code class=\"docutils literal notranslate\">Choice</code>. Następnie zmodyfikuj kod rejestracji <code class=\"docutils literal notranslate\">Question</code>, by wyglądał tak:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/admin.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Choice<span class=\"p\">,</span> Question\n\n\n<span class=\"k\">class</span> <span class=\"nc\">ChoiceInline</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>StackedInline<span class=\"p\">):</span>\n    model <span class=\"o\">=</span> Choice\n    extra <span class=\"o\">=</span> <span class=\"mi\">3</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    fieldsets <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span>               <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">]}),</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;Date information&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">],</span> <span class=\"s1\">&#39;classes&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;collapse&#39;</span><span class=\"p\">]}),</span>\n    <span class=\"p\">]</span>\n    inlines <span class=\"o\">=</span> <span class=\"p\">[</span>ChoiceInline<span class=\"p\">]</span>\n\nadmin<span class=\"o\">.</span>site<span class=\"o\">.</span>register<span class=\"p\">(</span>Question<span class=\"p\">,</span> QuestionAdmin<span class=\"p\">)</span>\n</code></pre></figure>\n<p>Mówi to Django: „Obiekty <code class=\"docutils literal notranslate\">Choice</code> są edytowane na stronie admina <code class=\"docutils literal notranslate\">Question</code>. Domyślnie wyświetl pól wystarczająco na 3 wybory”.</p>\n<p>Załaduj stronę „Add question”, by zobaczyć jak to wygląda:</p>\n<img alt=\"Add question page now has choices on it\" src=\"/pl/4.1/_images/admin10t.png\" />\n<p>Działa to tak: Są trzy miejsca na powiązane wybory – tak jak jest wskazane przez <code class=\"docutils literal notranslate\">extra</code> – i za każdym razem, kiedy powrócisz na stronę „Change dla już stworzonego obiektu, dostaniesz kolejne trzy dodatkowe miejsca.</p>\n<p>Na końcu trzech bieżących miejsc znajdziesz link „Add another Choice”. Jeśli w niego klikniesz, zostanie dodane nowe miejsce. Jeśli chcesz usunąć dodane miejsce, możesz kliknąć X w prawym górnym rogu dodanego miejsca. Ta grafika pokazuje dodane miejsce:</p>\n<img alt=\"Additional slot added dynamically\" src=\"/pl/4.1/_images/admin14t.png\" />\n<p>Jest jednak jeden mały problem. Wyświetlenie wszystkich pól do wypełnienia powiązanych obiektów <code class=\"docutils literal notranslate\">Choice</code> zajmuje ogromną ilość miejsca na ekranie. Z tego powodu Django oferuje sposób tabelaryczny na wyświetlenie „inline” powiązanych obiektów. Aby go użyć, zmień deklarację <code class=\"docutils literal notranslate\">ChoiceInline</code>, aby brzmiała:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/admin.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">class</span> <span class=\"nc\">ChoiceInline</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>TabularInline<span class=\"p\">):</span>\n    <span class=\"c1\">#...</span>\n</code></pre></figure>\n<p>Z <code class=\"docutils literal notranslate\">TabularInline</code> (zamiast <code class=\"docutils literal notranslate\">StackedInline</code>), powiązane obiekty są wyświetlane w bardziej zwartym, opartym na tabelce formacie:</p>\n<img alt=\"Add question page now has more compact choices\" src=\"/pl/4.1/_images/admin11t.png\" />\n<p>Note that there is an extra „Delete?” column that allows removing rows added\nusing the „Add another Choice” button and rows that have already been saved.</p>\n</section>\n<section id=\"customize-the-admin-change-list\">\n<h2>Dostosuj widok listy panelu administracyjnego<a class=\"heading-anchor\" href=\"#customize-the-admin-change-list\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Teraz, kiedy strona admina dla pytania wygląda dobrze, poprawmy nieco stronę „change list” – tę, która wyświetla wszystkie pytania w systemie.</p>\n<p>Tak ona wygląda w tym momencie:</p>\n<img alt=\"Polls change list page\" src=\"/pl/4.1/_images/admin04t.png\" />\n<p>Domyślnie Django wyświetla <code class=\"docutils literal notranslate\">str()</code> każdego obiektu. Ale czasem bardziej pomocne byłoby wyświetlanie poszczególnych pól. Aby to zrobić, użyj <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display\" title=\"django.contrib.admin.ModelAdmin.list_display\"><code class=\"xref py py-attr docutils literal notranslate\">list_display</code></a></p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/admin.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    list_display <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Na wszelki wypadek dodajmy też metodę <code class=\"docutils literal notranslate\">was_published_recently()</code> z <a class=\"reference internal\" href=\"/pl/4.1/intro/tutorial02/\"><span class=\"doc\">Tutoriala 2</span></a>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/admin.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    list_display <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;was_published_recently&#39;</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Teraz strona „change list” pytań wygląda w ten sposób:</p>\n<img alt=\"Polls change list page, updated\" src=\"/pl/4.1/_images/admin12t.png\" />\n<p>Możesz klikać w nagłówki kolumn, aby sortować po tych wartościach – z wyjątkiem przypadku nagłówka <code class=\"docutils literal notranslate\">was_published_recently</code>, ponieważ sortowanie po wyniku arbitralnej metody nie jest wspierane. Zwróć też uwagę, że nagłówek kolumny dla <code class=\"docutils literal notranslate\">was_published_recently</code> jest domyślnie nazwą metody (z podkreślnikami zamienionymi na spacje) i każda linia zawiera reprezentację w ciągu znaków wyniku.</p>\n<p>Możesz to poprawić używając dekoratora <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.display\" title=\"django.contrib.admin.display\"><code class=\"xref py py-func docutils literal notranslate\">display()</code></a> na tej metodzie (w <code class=\"file docutils literal notranslate\">polls/models.py</code>), w następujący sposób:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">polls/models.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n\n<span class=\"k\">class</span> <span class=\"nc\">Question</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"nd\">@admin</span><span class=\"o\">.</span>display<span class=\"p\">(</span>\n        boolean<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span>\n        ordering<span class=\"o\">=</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">,</span>\n        description<span class=\"o\">=</span><span class=\"s1\">&#39;Published recently?&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n    <span class=\"k\">def</span> <span class=\"nf\">was_published_recently</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        now <span class=\"o\">=</span> timezone<span class=\"o\">.</span>now<span class=\"p\">()</span>\n        <span class=\"k\">return</span> now <span class=\"o\">-</span> datetime<span class=\"o\">.</span>timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span> <span class=\"o\">&lt;=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>pub_date <span class=\"o\">&lt;=</span> now\n</code></pre></figure>\n<p>Po więcej informacji na temat właściwości konfigurowalnych przez ten dekorator, zobacz <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display\" title=\"django.contrib.admin.ModelAdmin.list_display\"><code class=\"xref py py-attr docutils literal notranslate\">list_display</code></a>.</p>\n<p>Zmień znów swój plik <code class=\"file docutils literal notranslate\">polls/admin.py</code> i dodaj ulepszenie do strony „change list” <code class=\"docutils literal notranslate\">Questions</code>: filtry, z użyciem <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter\" title=\"django.contrib.admin.ModelAdmin.list_filter\"><code class=\"xref py py-attr docutils literal notranslate\">list_filter</code></a>. Dodaj następującą linię do <code class=\"docutils literal notranslate\">QuestionAdmin</code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>list_filter <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>Doda to sidebar „Filter”, który pozwala ludziom filtrować listę obiektów używając pola <code class=\"docutils literal notranslate\">pub_date</code>:</p>\n<img alt=\"Polls change list page, updated\" src=\"/pl/4.1/_images/admin13t.png\" />\n<p>Typ wyświetlanego filtru zależy od typu pola, po którym filtrujesz. Ponieważ <code class=\"docutils literal notranslate\">pub_date</code> to <a class=\"reference internal\" href=\"/pl/4.1/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\">DateTimeField</code></a>, Django wie, aby dać odpowiednie opcje w filtrze: „Any date”, „Today”, „Past 7 days”, „This month”, „This year”.</p>\n<p>Dobrze się to zarysowuje. Dodajmy trochę możliwości wyszukiwania:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>search_fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>To dodaje pole wyszukiwania na górze „change listy”. Kiedy ktoś wprowadzi wyrażenie wyszukiwania, Django przeszuka pole <code class=\"docutils literal notranslate\">question_text</code>. Możesz użyć tyle pól, na ile masz ochotę – choć z powodu, że pod maską użyje to zapytania <code class=\"docutils literal notranslate\">LIKE</code>, ograniczenie liczby pól wyszukiwania do rozsądnej liczby ułatwi twojej bazie danych wykonać wyszukiwanie.</p>\n<p>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ę. <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_per_page\" title=\"django.contrib.admin.ModelAdmin.list_per_page\"><code class=\"xref py py-attr docutils literal notranslate\">Zmień paginację listy</code></a>, <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields\" title=\"django.contrib.admin.ModelAdmin.search_fields\"><code class=\"xref py py-attr docutils literal notranslate\">pola wyszukiwania</code></a>, <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter\" title=\"django.contrib.admin.ModelAdmin.list_filter\"><code class=\"xref py py-attr docutils literal notranslate\">filtry</code></a>, <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.date_hierarchy\" title=\"django.contrib.admin.ModelAdmin.date_hierarchy\"><code class=\"xref py py-attr docutils literal notranslate\">hierarchie dat</code></a> i:attr:kolejność kolumn nagłówków &lt;django.contrib.admin.ModelAdmin.list_display&gt; tak, aby wspólnie współgrały tak, jak uważasz, że powinny.</p>\n</section>\n<section id=\"customize-the-admin-look-and-feel\">\n<h2>Dostosuj wygląd i pracę z panelem administracyjnym<a class=\"heading-anchor\" href=\"#customize-the-admin-look-and-feel\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Oczywiście, wyświetlanie napisu „Django administration” na górze każdej strony panelu administracyjnego jest bez sensu. To tylko tekst zastępczy.</p>\n<p>Możesz go zmienić 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.</p>\n<section id=\"customizing-your-project-s-templates\">\n<span id=\"ref-customizing-your-projects-templates\"></span><h3>Dostosowywanie szablonów twojego <em>projektu</em><a class=\"heading-anchor\" href=\"#customizing-your-project-s-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Stwórz katalog <code class=\"docutils literal notranslate\">templates</code> w katalogu twojego projektu (tym, który zawiera <code class=\"docutils literal notranslate\">manage.py</code>). 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ą.</p>\n<p>Otwórz swój plik ustawiń (<code class=\"file docutils literal notranslate\">mysite/settings.py</code>, pamiętaj) i dodaj opcję <a class=\"reference internal\" href=\"/pl/4.1/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\">DIRS</code></a> w ustawieniu <a class=\"reference internal\" href=\"/pl/4.1/ref/settings/#std-setting-TEMPLATES\"><code class=\"xref std std-setting docutils literal notranslate\">TEMPLATES</code></a>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">mysite/settings.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code>TEMPLATES <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;BACKEND&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.template.backends.django.DjangoTemplates&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;DIRS&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span>BASE_DIR <span class=\"o\">/</span> <span class=\"s1\">&#39;templates&#39;</span><span class=\"p\">],</span>\n        <span class=\"s1\">&#39;APP_DIRS&#39;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;context_processors&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n                <span class=\"s1\">&#39;django.template.context_processors.debug&#39;</span><span class=\"p\">,</span>\n                <span class=\"s1\">&#39;django.template.context_processors.request&#39;</span><span class=\"p\">,</span>\n                <span class=\"s1\">&#39;django.contrib.auth.context_processors.auth&#39;</span><span class=\"p\">,</span>\n                <span class=\"s1\">&#39;django.contrib.messages.context_processors.messages&#39;</span><span class=\"p\">,</span>\n            <span class=\"p\">],</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p><a class=\"reference internal\" href=\"/pl/4.1/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\">DIRS</code></a> jest listą katalogów systemu plików, które należy sprawdzić ładując szablony Django; jest ścieżką wyszukiwania.</p>\n<aside class=\"admonition-organizing-templates admonition\" role=\"note\">\n<p class=\"admonition-title\">Organizacja szablonów</p>\n<p>Tak samo jak pliki statyczne, <em>moglibyśmy</em> 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. <code class=\"docutils literal notranslate\">polls/templates</code>) niż w katalogu szablonów projektu (<code class=\"docutils literal notranslate\">templates</code>). Omówimy bardziej szczegółowo w <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>samouczku aplikacji wielokrotnego użytku &lt;/intro/reusable-apps&gt;` <em>dlaczego</em> to robimy.</p>\n</aside>\n<p>Teraz stwórz katalog o nazwie <code class=\"docutils literal notranslate\">admin</code> wewnątrz <code class=\"docutils literal notranslate\">templates</code> i skopiuj szablon <code class=\"docutils literal notranslate\">admin/base_site.html</code> z katalogu domyślnych szablonów panelu administracyjnego z kodu źródłowego Django (<code class=\"docutils literal notranslate\">django/contrib/admin/templates</code>) do tego katalogu.</p>\n<aside class=\"admonition-where-are-the-django-source-files admonition\" role=\"note\">\n<p class=\"admonition-title\">Gdzie są pliki źródłowe Django?</p>\n<p>Jeśli masz trudność w odnalezieniu miejsca, gdzie są zlokalizowane pliki źródłowe Django w twoim systemie, uruchom następujące polecenie:</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-0-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python -c <span class=\"s2\">&quot;import django; print(django.__path__)&quot;</span>\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-0-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py -c <span class=\"s2\">&quot;import django; print(django.__path__)&quot;</span>\n</code></pre></div></div></div>\n</aside>\n<p>Następnie zmień plik i zamień <code class=\"docutils literal notranslate\">{{ site_header|default:_('Django administration')&#160; }}</code> (wliczając nawiasy klamrowe) na nazwę swojej strony, która będzie pasować. Powinieneś skończyć z sekcją kodu typu:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">branding</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">h1</span> <span class=\"na\">id</span><span class=\"o\">=</span><span class=\"s\">&quot;site-name&quot;</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;admin:index&#39;</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>Polls Administration<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Używamy tego podejścia, aby nauczyć cię jak nadpisywać szablony. W prawdziwym projekcie, prawdopodobnie użyłbyś atrybutu <a class=\"reference internal\" href=\"/pl/4.1/ref/contrib/admin/#django.contrib.admin.AdminSite.site_header\" title=\"django.contrib.admin.AdminSite.site_header\"><code class=\"xref py py-attr docutils literal notranslate\">django.contrib.admin.AdminSite.site_header</code></a>, aby w prostszy sposób zrobić tę konkretną zmianę.</p>\n<p>Ten plik szablonu zawiera pełno tekstów typu <code class=\"docutils literal notranslate\">{% block branding %}</code> i <code class=\"docutils literal notranslate\">{{ title }}</code>. Tagi <code class=\"docutils literal notranslate\">{%</code> i <code class=\"docutils literal notranslate\">{{</code> są częścią języka szablonów Django. Kiedy Django renderuje <code class=\"docutils literal notranslate\">admin/base_site.html</code>, ten język szablonów jest ewaluowany i produkuje ostateczną stronę HTML, tak jak widzieliśmy w <a class=\"reference internal\" href=\"/pl/4.1/intro/tutorial03/\"><span class=\"doc\">Tutorialu 3</span></a>.</p>\n<p>Zwróć uwagę, że każdy domyślny szablon panelu administracyjnego Django może być nadpisany. Aby nadpisać szablon, zrób tę samą czynność, którą zrobiłeś z <code class=\"docutils literal notranslate\">base_site.html</code> – skopiuj je z domyślnego katalogu do swojego własnego katalogu i zrób zmiany.</p>\n</section>\n<section id=\"customizing-your-application-s-templates\">\n<h3>Zmiana szablonów twojej <code class=\"docutils literal notranslate\">aplikacji</code><a class=\"heading-anchor\" href=\"#customizing-your-application-s-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Bystrzy czytelnicy zapytają: Ale skoro <a class=\"reference internal\" href=\"/pl/4.1/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\">DIRS</code></a> było domyślnie puste, jak Django odnajdywało domyślne szablony admina? Odpowiedzią jest, tak długo jak <a class=\"reference internal\" href=\"/pl/4.1/ref/settings/#std-setting-TEMPLATES-APP_DIRS\"><code class=\"xref std std-setting docutils literal notranslate\">APP_DIRS</code></a> jest ustawione na <code class=\"docutils literal notranslate\">True</code>, Django automatycznie szuka podkatalogu <code class=\"docutils literal notranslate\">templates/</code> w każdym pakiecie aplikacji, aby użyć go jako fallback (nie zapomnij, że <code class=\"docutils literal notranslate\">django.contrib.admin</code> jest aplikacją).</p>\n<p>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 <em>aplikacji</em> niż te w <em>projekcie</em>. 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.</p>\n<p>W <a class=\"reference internal\" href=\"/pl/4.1/topics/templates/#template-loading\"><span class=\"std std-ref\">dokumentacji ładowania szablonów</span></a> więcej informacji o tym, jak Django odnajduje swoje szablony.</p>\n</section>\n</section>\n<section id=\"customize-the-admin-index-page\">\n<h2>Dostosuj stronę indeksu panelu administracyjnego<a class=\"heading-anchor\" href=\"#customize-the-admin-index-page\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>W podobnym tonie możesz chcieć zmienić wygląd i odbiór strony indeksu panelu admina Django.</p>\n<p>Domyślnie wyświetla ona wszystkie aplikacje w <a class=\"reference internal\" href=\"/pl/4.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\">INSTALLED_APPS</code></a>, 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.</p>\n<p>Szablon do dostosowania to <code class=\"docutils literal notranslate\">admin/index.html</code>. (Zrób to samo co z <code class=\"docutils literal notranslate\">admin/base_site.html</code> 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 <code class=\"docutils literal notranslate\">app_list</code>. 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.</p>\n</section>\n<section id=\"what-s-next\">\n<h2>Co dalej?<a class=\"heading-anchor\" href=\"#what-s-next\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Tutorial dla początkujących kończy się tutaj. W międzyczasie możesz chcieć sprawdzić niektóre z kierunków wskazanych w <a class=\"reference internal\" href=\"/pl/4.1/intro/whatsnext/\"><span class=\"doc\">gdzie iść dalej</span></a>.</p>\n<p>Jeśli jesteś zaznajomiony z pakietowaniem w Pythonie i zainteresowany jak uczynić ankiety „aplikacją reusable”, sprawdź <a class=\"reference internal\" href=\"/pl/4.1/intro/reusable-apps/\"><span class=\"doc\">Zaawansowany tutorial: Jak pisać aplikacje do ponownego wykorzystania</span></a>.</p>\n</section>","rootId":"writing-your-first-django-app-part-7","toc":[{"title":"Dostosuj formularz panelu administracyjnego","anchor":"customize-the-admin-form","children":[]},{"title":"Dodawanie powiązanych obiektów","anchor":"adding-related-objects","children":[]},{"title":"Dostosuj widok listy panelu administracyjnego","anchor":"customize-the-admin-change-list","children":[]},{"title":"Dostosuj wygląd i pracę z panelem administracyjnym","anchor":"customize-the-admin-look-and-feel","children":[{"title":"Dostosowywanie szablonów twojego projektu","anchor":"customizing-your-project-s-templates","children":[]},{"title":"Zmiana szablonów twojej aplikacji","anchor":"customizing-your-application-s-templates","children":[]}]},{"title":"Dostosuj stronę indeksu panelu administracyjnego","anchor":"customize-the-admin-index-page","children":[]},{"title":"Co dalej?","anchor":"what-s-next","children":[]}],"breadcrumbs":[{"docname":"intro/index","title":"Pierwsze kroki","url":"/pl/4.1/intro/"}],"prev":{"docname":"intro/tutorial06","title":"Pisanie pierwszej aplikacji Django, część 6.","url":"/pl/4.1/intro/tutorial06/"},"next":{"docname":"intro/reusable-apps","title":"Zaawansowany tutorial: Jak pisać aplikacje wielokrotnego użytku","url":"/pl/4.1/intro/reusable-apps/"},"formats":{"html":"/pl/4.1/intro/tutorial07/","markdown":"/pl/4.1/intro/tutorial07.md","json":"/pl/4.1/intro/tutorial07.json"},"source":"https://github.com/django/django/blob/stable/4.1.x/docs/intro/tutorial07.txt","official":"https://docs.djangoproject.com/pl/4.1/intro/tutorial07/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}