{"title":"Escrevendo seu primeiro app Django, parte 7","version":"3.1","locale":"pt-br","docname":"intro/tutorial07","url":"/pt-br/3.1/intro/tutorial07/","canonical":"https://djangodocs.dev/pt-br/3.1/intro/tutorial07/","summary":"Esse tutorial começa onde o Tutorial 6 parou. Estamos continuando a aplicação Web para enquetes e focaremos na personalização do site administrativo automaticamente…","html":"<h1>Escrevendo seu primeiro app Django, parte 7<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-7\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Esse tutorial começa onde o <a class=\"reference internal\" href=\"/pt-br/3.1/intro/tutorial06/\"><span class=\"doc\">Tutorial 6</span></a> parou. Estamos continuando a aplicação Web para enquetes e focaremos na personalização do site administrativo automaticamente gerado pelo Django que exploramos no <a class=\"reference internal\" href=\"/pt-br/3.1/intro/tutorial02/\"><span class=\"doc\">Tutorial 2</span></a>.</p>\n<aside class=\"admonition-where-to-get-help admonition\">\n<p class=\"admonition-title\">Onde obter ajuda:</p>\n<p>Se tiver problemas enquanto caminha por este tutorial, por favor consulte a seção <a class=\"reference internal\" href=\"/pt-br/3.1/faq/help/\"><span class=\"doc\">Obtendo ajuda</span></a> da FAQ.</p>\n</aside>\n<section id=\"customize-the-admin-form\">\n<h2>Personalize o formulário do site de administração<a class=\"heading-anchor\" href=\"#customize-the-admin-form\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Ao registrarmos o modelo de <code class=\"docutils literal notranslate\"><span class=\"pre\">Question``através</span> <span class=\"pre\">da</span> <span class=\"pre\">linha</span> <span class=\"pre\">``admin.site.register(Question)</span></code>, o Django constrói um formulário padrão para representá-lo. Comumente, você desejará personalizar a apresentação e o funcionamento dos formulários do site de administração do Django. Para isto, você precisará informar ao Django as opções que você quer utilizar ao registrar o seu modelo.</p>\n<p>Vamos ver como isto funciona reordenando os campos no formulário de edição. Substitua a linha àdmin.site.register(Question)` por:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/admin.py</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=\"w\"> </span><span class=\"nn\">django.contrib</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">admin</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">ModelAdmin</span><span class=\"p\">):</span>\n    <span class=\"n\">fields</span> <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\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">Question</span><span class=\"p\">,</span> <span class=\"n\">QuestionAdmin</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Você seguirá este padrão – crie uma classe de “model admin”, em seguida, passe-a como o segundo argumento para o <code class=\"docutils literal notranslate\"><span class=\"pre\">admin.site.register()</span></code> – todas as vezes que precisar alterar as opções administrativas para um modelo.</p>\n<p>Essa mudança específica no código acima faz com que a “Publication date” apareça antes do campo “Question”:</p>\n<img alt=\"Fields have been reordered\" src=\"/pt-br/3.1/_images/admin07.png\" />\n<p>Isso não é impressionante com apenas dois campos, mas para formulários com dúzias deles, escolher uma ordem intuitiva é um detalhe importante para a usabilidade.</p>\n<p>E por falar em dúzias de campos, você pode querer dividir o formulário em grupos:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/admin.py</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=\"w\"> </span><span class=\"nn\">django.contrib</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">admin</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">ModelAdmin</span><span class=\"p\">):</span>\n    <span class=\"n\">fieldsets</span> <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\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">Question</span><span class=\"p\">,</span> <span class=\"n\">QuestionAdmin</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>O primeiro elemento de cada tupla em <a class=\"reference internal\" href=\"/pt-br/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets\" title=\"django.contrib.admin.ModelAdmin.fieldsets\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">fieldsets</span></code></a> é o título do grupo. Aqui está como o nosso formulário se parece agora:</p>\n<img alt=\"Form has fieldsets now\" src=\"/pt-br/3.1/_images/admin08t.png\" />\n</section>\n<section id=\"adding-related-objects\">\n<h2>Adicionando objetos relacionados<a class=\"heading-anchor\" href=\"#adding-related-objects\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Ok, nós temos nossa página de administração Questão, mas a <code class=\"docutils literal notranslate\"><span class=\"pre\">Questão</span></code> tem múltiplas <code class=\"docutils literal notranslate\"><span class=\"pre\">Questõe</span></code>s, e a página de administração não exibe escolhas.</p>\n<p>Ainda.</p>\n<p>There are two ways to solve this problem. The first is to register <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code>\nwith the admin just as we did with <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/admin.py</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=\"w\"> </span><span class=\"nn\">django.contrib</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">admin</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Choice</span><span class=\"p\">,</span> <span class=\"n\">Question</span>\n<span class=\"c1\"># ...</span>\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">Choice</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Agora “Choices” é uma opção disponível no site de administração do Django. O formulário de “Add choice” se parece com isto:</p>\n<img alt=\"Choice admin page\" src=\"/pt-br/3.1/_images/admin09.png\" />\n<p>Nesse formulário, o campo “Question” é uma caixa de seleção contendo todas as enquetes no banco de dados. O Django sabe que uma <a class=\"reference internal\" href=\"/pt-br/3.1/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ForeignKey</span></code></a> deve ser representada no site de administração como um campo <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;select&gt;</span></code>. No nosso caso, só existe uma enquete até agora.</p>\n<p>Observe também o link “Add Another” ao lado de “Question”. Todo objeto com um relacionamento de chave estrangeira para outro ganha essa opção gratuitamente. Quando você clica em “Add Another”, você terá uma janela popup com o formulário “Add question”. Se você adicionar uma enquete na janela e clicar em “Save”, o Django salvará a enquete no banco de dados e irá dinamicamente adicionar a opção já\nselecionada ao formulário “Add choice” que você está vendo.</p>\n<p>Mas, sério, essa é uma maneira ineficiente de adicionar objetos <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> ao sistema. Seria muito melhor se você pudesse adicionar várias opções diretamente quando criasse um objeto <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>. Vamos fazer isso acontecer.</p>\n<p>Remova a chamada <code class=\"docutils literal notranslate\"><span class=\"pre\">register()</span></code> do modelo <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code>. Então edite o código de registro de <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> para que fique assim:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/admin.py</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=\"w\"> </span><span class=\"nn\">django.contrib</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">admin</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Choice</span><span class=\"p\">,</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">ChoiceInline</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">StackedInline</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Choice</span>\n    <span class=\"n\">extra</span> <span class=\"o\">=</span> <span class=\"mi\">3</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">ModelAdmin</span><span class=\"p\">):</span>\n    <span class=\"n\">fieldsets</span> <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    <span class=\"n\">inlines</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"n\">ChoiceInline</span><span class=\"p\">]</span>\n\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">Question</span><span class=\"p\">,</span> <span class=\"n\">QuestionAdmin</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Isso informa ao Django: Objetos “<code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> são editados na mesma página de administração de <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>. Por padrão, forneça campos suficientes para 3 escolhas.”</p>\n<p>Carregue a página “Add question” para ver como está:</p>\n<img alt=\"Add question page now has choices on it\" src=\"/pt-br/3.1/_images/admin10t.png\" />\n<p>Funciona assim: há três blocos para Escolhas relacionadas – como especificado em <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> –, mas a cada vez que você retorna à página de “Alteração” para um objeto já criado, você ganha outros três blocos extra.</p>\n<p>At the end of the three current slots you will find an “Add another Choice”\nlink.  If you click on it, a new slot will be added. If you want to remove the\nadded slot, you can click on the X to the top right of the added slot. This\nimage shows an added slot:</p>\n<img alt=\"Additional slot added dynamically\" src=\"/pt-br/3.1/_images/admin14t.png\" />\n<p>One small problem, though. It takes a lot of screen space to display all the\nfields for entering related <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> objects. For that reason, Django offers a\ntabular way of displaying inline related objects. To use it, change the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">ChoiceInline</span></code> declaration to read:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/admin.py</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=\"w\"> </span><span class=\"nc\">ChoiceInline</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">TabularInline</span><span class=\"p\">):</span>\n    <span class=\"c1\">#...</span>\n</code></pre></figure>\n<p>Com o <code class=\"docutils literal notranslate\"><span class=\"pre\">TabularInline</span></code> (em vez de <code class=\"docutils literal notranslate\"><span class=\"pre\">StackedInline</span></code>), os objetos relacionados são exibidos de uma maneira mais compacta, formatada em tabela:</p>\n<img alt=\"Add question page now has more compact choices\" src=\"/pt-br/3.1/_images/admin11t.png\" />\n<p>Observe que há uma coluna extra “Delete?” que permite a remoção de linhas adicionadas usando o botão “Add Another Choice” e linhas que já foram salvas.</p>\n</section>\n<section id=\"customize-the-admin-change-list\">\n<h2>Personalize a listagem da página de administração<a class=\"heading-anchor\" href=\"#customize-the-admin-change-list\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Agora que a página de administração de Pergunta está bonita, vamos fazer algumas melhorias à página “change list” – aquela que exibe todas as enquetes do sistema.</p>\n<p>Aqui é como ela está até agora:</p>\n<img alt=\"Polls change list page\" src=\"/pt-br/3.1/_images/admin04t.png\" />\n<p>Por padrão, o Django mostra o <code class=\"docutils literal notranslate\"><span class=\"pre\">str()</span></code> de cada objeto. Mas algumas vezes seria mais útil se pudéssemos mostrar campos individuais. Para fazer isso, use a opção <a class=\"reference internal\" href=\"/pt-br/3.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\"><span class=\"pre\">list_display</span></code></a>, que é uma tupla de nomes de campos a serem exibidos, como colunas, na lista de mudança dos objetos:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/admin.py</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=\"w\"> </span><span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">ModelAdmin</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"n\">list_display</span> <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>For good measure, let’s also include the <code class=\"docutils literal notranslate\"><span class=\"pre\">was_published_recently()</span></code> method\nfrom <a class=\"reference internal\" href=\"/pt-br/3.1/intro/tutorial02/\"><span class=\"doc\">Tutorial 2</span></a>:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/admin.py</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=\"w\"> </span><span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">ModelAdmin</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"n\">list_display</span> <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>Agora a página de edição de enquetes está assim:</p>\n<img alt=\"Polls change list page, updated\" src=\"/pt-br/3.1/_images/admin12t.png\" />\n<p>Você pode clicar no cabeçalho da coluna para ordená-las por estes valores – exceto no caso do <code class=\"docutils literal notranslate\"><span class=\"pre\">was_published_recently</span></code>, porque a ordenação pelo resultado de um método arbitrário não é suportada. Também note que o cabeçalho da coluna\npara <code class=\"docutils literal notranslate\"><span class=\"pre\">was_published_recently</span></code> é, por padrão, o nome do método (com underscores substituídos por espaços), e que cada linha contem a representação da saída.</p>\n<p>Você pode melhorar isso adicionando ao método (em <code class=\"file docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code>) alguns atributos, como segue:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/models.py</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=\"w\"> </span><span class=\"nc\">Question</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">was_published_recently</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">now</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"n\">now</span> <span class=\"o\">-</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><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><span class=\"n\">pub_date</span> <span class=\"o\">&lt;=</span> <span class=\"n\">now</span>\n    <span class=\"n\">was_published_recently</span><span class=\"o\">.</span><span class=\"n\">admin_order_field</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;pub_date&#39;</span>\n    <span class=\"n\">was_published_recently</span><span class=\"o\">.</span><span class=\"n\">boolean</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n    <span class=\"n\">was_published_recently</span><span class=\"o\">.</span><span class=\"n\">short_description</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;Published recently?&#39;</span>\n</code></pre></figure>\n<p>Para obter mais informações sobre essas propriedades de método, veja :attr:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>~django.contrib.admin.ModelAdmin.list_display.</p>\n<p>Edite o arquivo <code class=\"file docutils literal notranslate\"><span class=\"pre\">polls/admin.py</span></code> de novo e adicione uma melhoria à  página de lista de edição <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>: Um filtro usando <a class=\"reference internal\" href=\"/pt-br/3.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\"><span class=\"pre\">list_filter</span></code></a>. Adicione a seguinte linha ao <code class=\"docutils literal notranslate\"><span class=\"pre\">QuestionAdmin</span></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><span class=\"n\">list_filter</span> <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>Isso adiciona uma barra lateral “Filter” que permite às pessoas filtrarem a lista de edição pelo campo <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code>:</p>\n<img alt=\"Polls change list page, updated\" src=\"/pt-br/3.1/_images/admin13t.png\" />\n<p>O tipo do filtro apresentado depende do tipo do campo pelo qual você está filtrando. Como <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code> é uma instância da classe  <a class=\"reference internal\" href=\"/pt-br/3.1/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a>, o Django consegue deduzir que os filtros apropriados são: “Qualquer data”, “Hoje”, “Últimos 7 dias”, “Esse mês”, “Esse ano”.</p>\n<p>Isso está ficando bom. Vamos adicionar capacidade de pesquisa:</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><span class=\"n\">search_fields</span> <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>Isso adiciona um campo de pesquisa ao topo da lista de edição. Quando alguém informa termos de pesquisa, o Django irá pesquisar o campo <code class=\"docutils literal notranslate\"><span class=\"pre\">question_text</span></code>. Você pode usar quantos campos quiser – entretanto, por ele usar uma consulta <code class=\"docutils literal notranslate\"><span class=\"pre\">LIKE</span></code> internamente, limitar o número de campos de pesquisa a um número razoável, será mais fácil para o seu banco de dados para fazer pesquisas.</p>\n<p>Agora é também uma boa hora para observar que a página de edição fornece uma paginação gratuitamente. O padrão é mostrar 100 itens por página. <a class=\"reference internal\" href=\"/pt-br/3.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\"><span class=\"pre\">Paginação</span> <span class=\"pre\">da</span> <span class=\"pre\">página</span> <span class=\"pre\">de</span> <span class=\"pre\">edição</span></code></a>, <a class=\"reference internal\" href=\"/pt-br/3.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\"><span class=\"pre\">campos</span> <span class=\"pre\">de</span> <span class=\"pre\">pesquisa</span></code></a>, <a class=\"reference internal\" href=\"/pt-br/3.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\"><span class=\"pre\">filters</span></code></a>, <a class=\"reference internal\" href=\"/pt-br/3.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\"><span class=\"pre\">hierarquia</span> <span class=\"pre\">por</span> <span class=\"pre\">data</span></code></a>, e <a class=\"reference internal\" href=\"/pt-br/3.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\"><span class=\"pre\">ordenação</span> <span class=\"pre\">por</span> <span class=\"pre\">cabeçalho</span> <span class=\"pre\">de</span> <span class=\"pre\">coluna</span></code></a> todos trabalham em sincronia como deveriam.</p>\n</section>\n<section id=\"customize-the-admin-look-and-feel\">\n<h2>Personalize a aparência do site de administração<a class=\"heading-anchor\" href=\"#customize-the-admin-look-and-feel\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Obviamente, ter “Django administration” no topo de cada página de administração é ridículo. Isso é só um texto de exemplo.</p>\n<p>You can change it, though, using Django’s template system. The Django admin is\npowered by Django itself, and its interfaces use Django’s own template system.</p>\n<section id=\"customizing-your-project-s-templates\">\n<span id=\"ref-customizing-your-projects-templates\"></span><h3>Personalize os templates do seu <em>projeto</em><a class=\"heading-anchor\" href=\"#customizing-your-project-s-templates\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Criar um diretório <code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code> no diretório do seu projeto (aquela que contém <code class=\"docutils literal notranslate\"><span class=\"pre\">manage.py</span></code>). Os modelos podem viver em qualquer lugar em seu sistema de arquivos que o Django possa acessar. (Django é executado como qualquer usuário que seu servidor é executado.) No entanto, manter seus templates dentro do projeto é uma boa convenção a seguir.</p>\n<p>Abra seu arquivo de configurações (<code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code>, lembre-se) e adicione uma opção  <a class=\"reference internal\" href=\"/pt-br/3.1/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DIRS</span></code></a>. na configuração <a class=\"reference internal\" href=\"/pt-br/3.1/ref/settings/#std-setting-TEMPLATES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TEMPLATES</span></code></a> setting:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">mysite/settings.py</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=\"n\">TEMPLATES</span> <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><span class=\"n\">BASE_DIR</span> <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=\"/pt-br/3.1/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DIRS</span></code></a> é uma lista de diretórios de arquivos que serão checados quando o Django carregar seus templates, ou seja, caminhos de busca.</p>\n<aside class=\"admonition-organizing-templates admonition\">\n<p class=\"admonition-title\">Organizando templates</p>\n<p>Just like the static files, we <em>could</em> have all our templates together, in\none big templates directory, and it would work perfectly well. However,\ntemplates that belong to a particular application should be placed in that\napplication’s template directory (e.g. <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates</span></code>) rather than the\nproject’s (<code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code>). We’ll discuss in more detail in the\n<a class=\"reference internal\" href=\"/pt-br/3.1/intro/reusable-apps/\"><span class=\"doc\">reusable apps tutorial</span></a> <em>why</em> we do this.</p>\n</aside>\n<p>Agora crie um diretório chamado <code class=\"docutils literal notranslate\"><span class=\"pre\">admin</span></code> dentro de <code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code>, e copie o template <code class=\"docutils literal notranslate\"><span class=\"pre\">admin/base_site.html</span></code> de dentro do diretório padrão do site de administração do Django (<code class=\"docutils literal notranslate\"><span class=\"pre\">django/contrib/admin/templates</span></code>) para dentro deste diretório.</p>\n<aside class=\"admonition-where-are-the-django-source-files admonition\">\n<p class=\"admonition-title\">Onde estão os arquivos de código-fonte do Django?</p>\n<p>Se você tiver dificuldade em encontrar onde os arquivos do Django estão localizados em seu sistema, execute o seguinte comando:</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<span class=\"w\"> </span>-c<span class=\"w\"> </span><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>Então, edite o arquivo e substitua <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span> <span class=\"pre\">site_header|default:_('Django</span> <span class=\"pre\">administration')</span> <span class=\"pre\">}}</span></code> (incluindo as chaves) com nome do seu próprio site como desejar. Você deve acabar com uma secção de código como:</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>Nós usamos esta abordagem para ensinar-lhe como substituir templates. Em um projeto real, você provavelmente usaria o atributo <a class=\"reference internal\" href=\"/pt-br/3.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\"><span class=\"pre\">django.contrib.admin.AdminSite.site_header</span></code></a> para fazer mais facilmente essa personalização em particular.</p>\n<p>Esse template contém uma série de textos como <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">block</span> <span class=\"pre\">branding</span> <span class=\"pre\">%}</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span> <span class=\"pre\">tittle</span> <span class=\"pre\">}}</span></code>. As tags <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span></code> e <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span></code> fazem pate da linguagem de templates do Django. Quando o Django renderiza o template “admin/base_site.html”, o seu conteúdo é processado por essa linguagem de templates para produzir a página HTML final, assim como vimos no <a class=\"reference internal\" href=\"/pt-br/3.1/intro/tutorial03/\"><span class=\"doc\">Tutorial 3</span></a>.</p>\n<p>Note que qualquer template padrão do site de administração pode ser sobrescrito. Para sobrescrever um template, apenas faça a mesma coisa que você fez com <code class=\"docutils literal notranslate\"><span class=\"pre\">base_site.html</span></code> – copie ele do diretório padrão para o seu próprio diretório, e faça as mudanças.</p>\n</section>\n<section id=\"customizing-your-application-s-templates\">\n<h3>Personalize os templates da sua <em>aplicação</em><a class=\"heading-anchor\" href=\"#customizing-your-application-s-templates\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Leitores astutos irão se perguntar: Mas se <a class=\"reference internal\" href=\"/pt-br/3.1/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DIRS</span></code></a> estava vazio por padrão, como o Django pôde encontrar o diretório padrão dos templates do site de administração? A resposta é, Desde que <a class=\"reference internal\" href=\"/pt-br/3.1/ref/settings/#std-setting-TEMPLATES-APP_DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">APP_DIRS</span></code></a> seja <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>, o Django irá automaticamente procurar por um subdiretório <code class=\"docutils literal notranslate\"><span class=\"pre\">templates/</span></code> dentro de cada pacote de aplicação, para usar como fallback(Não esqueça que <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.admin</span></code> é uma aplicação)</p>\n<p>Nossa aplicação de enquetes não é muito complexa e não precisa de templates personalizados para o site de administração. Mas se ele crescer e ficar mais sofisticado e necessária a modificação dos templates padrão de administração do Django para algumas de suas funcionalidades, seria mais sensato  modificar os templates da <em>aplicação</em>, e não os do <em>projeto</em>. Dessa forma, você poderia incluir a aplicação de enquete em qualquer novo projeto e ter a certeza que iria encontrar os templates personalizados que você precisa.</p>\n<p>Veja a <a class=\"reference internal\" href=\"/pt-br/3.1/ref/templates/api/#template-loaders\"><span class=\"std std-ref\">documentação de carga de template</span></a> - para mais informação sobre como o Django acha seus templates.</p>\n</section>\n</section>\n<section id=\"customize-the-admin-index-page\">\n<h2>Personalize a página inicial do site de administração<a class=\"heading-anchor\" href=\"#customize-the-admin-index-page\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>De maneira similar, você pode querer personalizar a aparência da página inicial do site de administração do Django.</p>\n<p>Por padrão, ele exibe todas as aplicações em <a class=\"reference internal\" href=\"/pt-br/3.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>, que estão registrados na aplicação de administração, em ordem alfabética. E você pode querer fazer alterações significativas no layout. Além do que, a página inicial é provavelmente a página mais importante da página de administração, e deve ser fácil de usar.</p>\n<p>O template para personalizar é <code class=\"docutils literal notranslate\"><span class=\"pre\">admin/index.html</span></code>. (Faça o mesmo que <code class=\"docutils literal notranslate\"><span class=\"pre\">admin/base_site.html</span></code> na seção anterior – copie ele do diretório padrão para o seu diretório de template personalizado). Edite o arquivo e você verá que ele usa uma variável de template chamada <code class=\"docutils literal notranslate\"><span class=\"pre\">app_list</span></code>. Esta variável contém cada aplicação instalada no Django. Ao invés de usar isto, você pode criar links diretos para páginas do site de administração específicas em qualquer forma que você achar melhor.</p>\n</section>\n<section id=\"what-s-next\">\n<h2>E agora?<a class=\"heading-anchor\" href=\"#what-s-next\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>O tutorial dos iniciantes termina aqui. Entretanto, você pode querer verificar alguns indicadores em <a class=\"reference internal\" href=\"/pt-br/3.1/intro/whatsnext/\"><span class=\"doc\">onde ir partindo daqui</span></a>.</p>\n<p>Se você é familiar ao sistema de empacotamento Python e está interessado em como tornar a enquete em uma “app reusável”, veja <a class=\"reference internal\" href=\"/pt-br/3.1/intro/reusable-apps/\"><span class=\"doc\">Tutorial avançado: como escrever apps reusáveis</span></a>.</p>\n</section>","rootId":"writing-your-first-django-app-part-7","toc":[{"title":"Personalize o formulário do site de administração","anchor":"customize-the-admin-form","children":[]},{"title":"Adicionando objetos relacionados","anchor":"adding-related-objects","children":[]},{"title":"Personalize a listagem da página de administração","anchor":"customize-the-admin-change-list","children":[]},{"title":"Personalize a aparência do site de administração","anchor":"customize-the-admin-look-and-feel","children":[{"title":"Personalize os templates do seu projeto","anchor":"customizing-your-project-s-templates","children":[]},{"title":"Personalize os templates da sua aplicação","anchor":"customizing-your-application-s-templates","children":[]}]},{"title":"Personalize a página inicial do site de administração","anchor":"customize-the-admin-index-page","children":[]},{"title":"E agora?","anchor":"what-s-next","children":[]}],"breadcrumbs":[{"docname":"intro/index","title":"Introdução","url":"/pt-br/3.1/intro/"}],"prev":{"docname":"intro/tutorial06","title":"Escrevendo sua primeira aplicação Django, parte 6","url":"/pt-br/3.1/intro/tutorial06/"},"next":{"docname":"intro/reusable-apps","title":"Tutorial avançado: Como escrever aplicações reutilizáveis","url":"/pt-br/3.1/intro/reusable-apps/"},"formats":{"html":"/pt-br/3.1/intro/tutorial07/","markdown":"/pt-br/3.1/intro/tutorial07.md","json":"/pt-br/3.1/intro/tutorial07.json"},"source":"https://github.com/django/django/blob/stable/3.1.x/docs/intro/tutorial07.txt","official":"https://docs.djangoproject.com/pt-br/3.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","1.9"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}