O site admin do Django¶
Uma das mais poderosas partes do Django é a inteface de administração automática. Ela lê os metadados de seu model para fornecer uma inteface poderosa e pronta para produção que produtores de conteúdo podem imediatamente usar para começar a adicionar conteúdos ao site. Neste documento, nós discutimos como ativar, usar e personalizar a interface de administração do Django.
Nota
O site admin foi significantemente refatorado desde a versão 0.96. Este documento descreve a versão mais nova do site admin, que permite customizações mais ricas. Se você acompanha o desenvolvimento do Django em si, você pode ter ouvido isso descrito como “newforms-admin.”
Visão geral¶
Há cinco passos para ativar o site admin do Django:
- Adicione
django.contrib.admin
no seuINSTALLED_APPS
. - Determine quais models de aplicações devem ser editados pela interface admin.
- Para cada um destes models, opicionalmente, crie uma classe
ModelAdmin
que encapsula as funcionalidades customizadas do admin e opções para este model particular. - Instancie um
AdminSite
e o informe sobre cada um de seus models e classesModelAdmin
. - Ligue a instância
AdminSite
ao seu URLconf.
See also
Para informações sobre como servir arquivos de mídia (imagens, JavaScript, e CSS) associado ao admin em produção, veja Servindo arquivos de mídia.
Objetos ModelAdmin
¶
-
class
ModelAdmin
¶
A classe ModelAdmin
é a representação de um model na interface de
administração. Este são armazenados num arquivo chamado admin.py
na sua
aplicação. Vamos dar uma olhada num exemplo muito simples de ModelAdmin
:
from django.contrib import admin
from myproject.myapp.models import Author
class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)
Você precisa de um objeto ModelAdmin
sempre?
No exemplo anterior, a classe ModelAdmin
não define quaisquer valores
personalizados (ainda). Como um resultado, a interface admin padrão será
fornecida. Se você estiver feliz com a interface admin padrão, você não
precisa definir um objeto ModelAdmin
sempre – você poder registrar a
classe model sem fornecer uma descrição do ModelAdmin
. O exemplo
anterior poderia ser simplicado para:
from django.contrib import admin
from myproject.myapp.models import Author
admin.site.register(Author)
Opções ModelAdmin
¶
O ModelAdmin
é muito flexível. Ele tem várias opções para lidar com
customização da interface. Todas as opções são definidas na subclasse
ModelAdmin
:
class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = 'pub_date'
-
ModelAdmin.
date_hierarchy
¶
Sete o date_hierarchy
com o nome de um DateField
ou DateTimeField
do
seu model, e a lista de dados incluirá uma navegação por data, utilizando o
campo informado.
Exemplo:
date_hierarchy = 'pub_date'
-
ModelAdmin.
form
¶
Por padrão um ModelForm
é dinamicamente criado para seu model. Ele é usado
para criar o formulário apresentado em ambas as páginas adicionar/editar. Você
pode facilmente fornecer seu próprio ModelForm
para sobrescrever qualquer
comportamento de formulário nas páginas adicionar/editar.
Para um exemplo veja a seção Adicionando validação personalizada ao admin.
-
ModelAdmin.
fieldsets
¶
Sete fieldsets
para controlar o layout das páginas “adicionar” e “editar” do
admin.
fieldsets
é uma lista de tuplas duplas, em que cada tupla dupla representa
um <fieldset>
sobre a página de formulário do admin. (Um <fieldset>
é
uma “seção” do formulário.)
As tuplas duplas estão no formato (name, field_options)
, onde name
é uma
string representando o título do fieldset e field_options
é um dicionário
com informações sobre o fieldset, incluíndo uma lista de campos para serem
mostrados nele.
Um exemplo completo, recebido do model django.contrib.flatpages.FlatPage
:
class FlatPageAdmin(admin.ModelAdmin):
fieldsets = (
(None, {
'fields': ('url', 'title', 'content', 'sites')
}),
('Advanced options', {
'classes': ('collapse',),
'fields': ('enable_comments', 'registration_required', 'template_name')
}),
)
Isso resulta numa página admin que parece com:
Se o fieldsets
não for fornecido, o Django mostrará o padrão de cada campo
que não for um AutoField
e tenha um editable=True
, em um fieldset único,
na mesma ordem em que os campos foram definidos no model.
O dicionário field_optinos
pode ter as seguintes chaves:
fields
Uma tupla com nomes de campos que serão mostrados no fieldset. Esta chave é obrigatória.
Exemplo:
{ 'fields': ('first_name', 'last_name', 'address', 'city', 'state'), }
Para mostrar vários campos na mesma linha, envolva-os em suas próprias tuplas. Neste exemplo, os campos
first_name
elast_name
serão mostrados na mesma linha:{ 'fields': (('first_name', 'last_name'), 'address', 'city', 'state'), }
classes
Uma lista contendo classes extra de CSS para serem aplicadas ao fieldset.
Exemplo:
{ 'classes': ['wide', 'extrapretty'], }
Duas classes úteis definidas por padrão no site admin são
collapse
ewide
. Os fieldsets com o estilocollapse
serão inicialmente encolhidos no admin e substituídos por um link “click para expandir”. Os fieldsets com o estilowide
ocuparão um espaço horizontal extra.
description
Uma string de texto opcional extra para ser mostrado no topo de cada fieldset, abaixo do cabeçalho do fieldset.
Note que este valor não tem o HTML escapado quando é mostrado na interface do admin. Isso permite você incluir HTML se assim desejar. Aleternativamente você poder usar texto plano e
django.utils.html.escape()
para escapar quaisquer caracteres especiais de HTML.
-
ModelAdmin.
fields
¶
Use esta opção como uma alternativa ao fieldsets
se o layout não importar
e se você deseja somente mostrar um sub-conjunto de campos disponíveis no
formulário. Por exemplo, você poderia definir uma versão mais simples do
formulário do admin para o model django.contrib.flatpages.FlatPage
desta
forma:
class FlatPageAdmin(admin.ModelAdmin):
fields = ('url', 'title', 'content')
No exemplo acima, somente os campos ‘url’, ‘title’ e ‘content’ serão mostrados, sequencialmente, no formulário.
Nota
Estas opções fields
não devem ser confundidas com a chave de dicionário
fields
que fica dentro da opção fieldsets
, como descrito na seção
anterior.
-
ModelAdmin.
exclude
¶
Este atributo, se fornecido, deve ser uma lista com nomes de campos a se escluir do formulário.
Por exemplo, vamos considerar o seguinte model:
class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3)
birth_date = models.DateField(blank=True, null=True)
Se você deseja um formulário do model Author
que inclui somente os campos
name
e title
, você poderia especificar fields
ou exclude
desta
forma:
class AuthorAdmin(admin.ModelAdmin):
fields = ('name', 'title')
class AuthorAdmin(admin.ModelAdmin):
exclude = ('birth_date',)
Assim o model Author somente terá três campos, name
, title
, e
birth_date
, os formulários resultantes das declarações acima conterão
extamante os mesmos campos.
-
ModelAdmin.
filter_horizontal
¶
Use a nifty unobtrusive JavaScript “filter” interface instead of the
usability-challenged <select multiple>
in the admin form. The value is a
list of fields that should be displayed as a horizontal filter interface. See
filter_vertical
to use a vertical interface.
-
ModelAdmin.
filter_vertical
¶
O mesmo que filter_horizontal
, mas é um display vertical do filtro.
-
ModelAdmin.
list_display
¶
Configure o list_display
para controlar quais campos são mostrados na
listagem do admin.
Exemplo:
list_display = ('first_name', 'last_name')
Se você não seta list_display
, o site admin mostrará uma única coluna que
mostra o __unicode__()
representando cada objeto.
Você tem quatro valores possível que podem ser usado no list_display
:
Uma campo de model. Por exemplo:
class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name')
Uma função que aceita um paramêtro para a instância do model. Por exemplo:
def upper_case_name(obj): return ("%s %s" % (obj.first_name, obj.last_name)).upper() upper_case_name.short_description = 'Name' class PersonAdmin(admin.ModelAdmin): list_display = (upper_case_name,)
Uma string representando um atributo no
ModelAdmin
. Este se comporta da mesma forma que a função acima. Por exemplo:class PersonAdmin(admin.ModelAdmin): list_display = ('upper_case_name',) def upper_case_name(self, obj): return ("%s %s" % (obj.first_name, obj.last_name)).upper() upper_case_name.short_description = 'Name'
Uma string representando um atributo no model. Este se comporta quase como a função acima, a diferença é que o
self
neste contexto é a instância do model. Aqui temos um exemplo completo:class Person(models.Model): name = models.CharField(max_length=50) birthday = models.DateField() def decade_born_in(self): return self.birthday.strftime('%Y')[:3] + "0's" decade_born_in.short_description = 'Birth decade' class PersonAdmin(admin.ModelAdmin): list_display = ('name', 'decade_born_in')
Uns poucos casos especiais para se tomar nota sobre o list_display
:
* Se o campo é um ``ForeignKey``, o Django mostrará o ``__unicode`__()`` do
objeto relacionado.
* Campos ``ManyToManyField`` não são suportados, pois poderiam implicar em
execução de consultas SQL em separado pra cada linha da tabela. Se você
deseja fazer isso de qualquer forma, dê ao seu model um método
personalizado, e adicione o nome desse método no ``list_display``. (Veja
abaixo para saber mais sobre métodos personalizados no ``list_display``.)
* Se o campo é um ``BooleanField`` ou ``NullBooleanField``, o Django
mostrará um belo ícone "on" ou "off" ao invés de ``True`` ou ``False``.
* Se a string fornecida é um método do model, ``ModelAdmin`` ou uma função,
o Django espacará o HTML da saída por padrão. Se você gostaria de não
escapar a saída do método, de ao método um atributo ``allow_tags`` cujo o
valor é ``True``.
Aqui temos um exemplo completo::
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
def colored_name(self):
return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name)
colored_name.allow_tags = True
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'colored_name')
* Se a string dada é um método do model, ``ModelAdmin`` ou uma função que
retorna True ou False o Django mostrará um belo ícone "on" ou "off" se
você der ao método um atributo ``boolean`` cujo o valor é ``True``.
Aqui temos um exemplo completo do model::
class Person(models.Model):
first_name = models.CharField(max_length=50)
birthday = models.DateField()
def born_in_fifties(self):
return self.birthday.strftime('%Y')[:3] == '195'
born_in_fifties.boolean = True
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'born_in_fifties')
* Os métodos ``__str__()`` e ``__unicode__()`` não só são válidos no
``list_display`` como em qualquer outro método de model, então é
perfeitamente OK usar isso::
list_display = ('__unicode__', 'some_other_field')
* Normalmente, os elementos do ``list_display`` que não estão dentre os
campos do bancos de dados atual não podem ser usado em ordenamentos (pois
o Django não sabe como sortealos a nível de banco de dados).
Entretanto, se um elemento de um ``list_display`` representa um certo
campo do banco de dados, você pode indicar este fato configurando o
atributo ``admin_order_field`` do item.
Por exemplo::
class Person(models.Model):
first_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
def colored_first_name(self):
return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
colored_first_name.allow_tags = True
colored_first_name.admin_order_field = 'first_name'
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'colored_first_name')
O exemplo acima dirá ao Django para ordenar o campo ``first_name`` quando
tentar sortear pelo ``colored_first_name`` no admin.
-
ModelAdmin.
list_display_links
¶
Seta um list_display_links
para controlar quais campos no list_display
deveriam ser linkados à página de edição de um objeto.
Por padrão, a página de listagem linkará a primeira coluna – o primeiro campo
especificado no list_display
– para a página de edição de cada item. Mas
list_display_links
permite você mudar quais colunas serão linkadas.
Configure list_display_links
com uma lista de tuplas com nomes de campos (no
mesmo formato como list_display
) para linkar.
O list_display_links
pode especificar um ou mais nomes de campos. Tantos
quanto os nomes dos campos que aparecerem no list_display
, o Django não se
preocupa com quantos campos (ou quão poucos) serão linkados. O único requisito
é: Se você usar list_display_links
, você deve definir list_display
.
Neste exemplo, os campos first_name
e last_name
serão linkados na página
de listagem:
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'birthday')
list_display_links = ('first_name', 'last_name')
-
ModelAdmin.
list_filter
¶
Configure o list_filter
para ativar os filtros na barra à direita da
listagem do admin. Este deve ser uma lista de nomes de campos, e cada campo
especificado devem ser BooleanField
, CharField
, DateField
,
DateTimeField
, IntegerField
ou ForeignKey
.
Este exemplo, pêgo do model django.contrib.auth.models.User
, mostra como
ambos list_display
e list_filter
funcionam:
class UserAdmin(admin.ModelAdmin):
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser')
O código acima resulta numa página de listagem do admim que parece com este:
(Este exemplo tem um search_fields
definido. Veja abaixo.)
-
ModelAdmin.
list_per_page
¶
Configure o list_per_page
para controlar quantos ítens devem aparecer em
cada página da paginação da listagem. Por padrão, é setado para 100
.
Configure list_select_related
para dizer ao Django para usar
select_related()
na lista de objetos recebida na listagem do admin. Isso
pode poupar um monte de consultas no banco de dados.
O valor deve ser True
ou False
. O padrão é False
.
Note que o Django usará select_related()
, indiferente desta configuração,
se um dos campos no list_display
for um ForeignKey
.
Para mais sobre select_related()
, veja
a documentação do select_related().
-
ModelAdmin.
inlines
¶
Veja objetos InlineModelAdmin
abaixo.
-
ModelAdmin.
ordering
¶
Configure ordering
para especificar como os objetos na listagem do admin
devem ser ordenados. Este deve ser uma lista de tuplas no mesmo formato do
parâmetro ordering
do model.
Se este não for fornecido, o Django admin usará o ordenamento padrão do model.
Nota
O Django somente honra o primeiro elemento na lista/tupla; qualquer outro será ignorado.
-
ModelAdmin.
prepopulated_fields
¶
Configure prepopulated_fields
com um mapeamento num dicionário com os campos
que devem ser pré-populados a partir de outro campo:
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
Quando configurado, os campos dados usaram um pouco de JavaScript para popular
os campos atribuídos. O principal uso para esta funcionalidade é a de
automaticamente gerar um valor para campos SlugField
a partir de um ou mais
campos. O valor gerado é produzido concatenando os valores do campo originário,
e então transformando este resultado num slug válido (e.g. substituíndo barras
por espaços).
O prepopulated_fields
não aceita campos DateTimeField
, ForeignKey
,
nem ManyToManyField
.
-
ModelAdmin.
radio_fields
¶
Por padrão, o admin do Django usa uma interface com select-box (<select>) para
campos que são ForeignKey
ou que tem choices
configurado. Se um campo é
apresentado no radio_fields
, o Django usará uma interface com radio-button
ao invés. Assumindo que group
é um ForeignKey
no model Person
:
class PersonAdmin(admin.ModelAdmin):
radio_fields = {"group": admin.VERTICAL}
Você tem a escolha de usar HORIZONTAL
ou VERTICAL
do módulo
django.contrib.admin
.
Não inclua um campo no radio_fields
a menos que seja um ForeignKey
ou
tenha choices
setado.
-
ModelAdmin.
raw_id_fields
¶
Por padrão, o admin do Django usa um select-box (<select>) para campos que são
ForeignKey
. Algumas vezes você pode não desejar ficar sujeito a um overhead
ao selecionar todos as instâncias relacionadas num drop-down.
O raw_id_fields
é uma lista de campos que você gostaria de mudar dentro de
um widget Input
tanto para ForeignKey
quanto ManyToManyField
:
class ArticleAdmin(admin.ModelAdmin):
raw_id_fields = ("newspaper",)
-
ModelAdmin.
save_as
¶
Seta save_as
para habilitar um “save as” no formulário de edição do admin.
Normalmente, objetos tem três opções de salve: “Salvar”, “Salvar e continuar
editando” e “Salvar e adicionar outro”. Se save_as
for True
, o “Salvar e
adicionar outro” será substituído por um botão “Salvar como”.
Nota do tradutor
Se você não estiver utilizando uma versão do Django traduzida, os botões “Salvar e continuar editando”, “Salvar”, “Salvar e adicionar outro” e “Salvar como”, serão, respectivamente, “Save”, “Save and continue editing”, “Save and add another” e “Save as”.
“Salvar como” significa que o objeto será salvo como um novo objeto (com um novo ID), ao invés de um objeto já existente.
Por padrão, save_as
é setado como False
.
-
ModelAdmin.
save_on_top
¶
Seta save_on_top
para adicionar os botões de salvar no topo do formulário
de edição do admin.
Normalmente, os botões salvar aparecem somente na base do formulário. Se você
setar save_on_top
, os botões aparecerão em ambos os lugares, na base e no
topo.
Por padrão, save_on_top
é setado como False
.
-
ModelAdmin.
search_fields
¶
Configure search_fields
para habilitar uma caixa de busca na página de
listagem do admin. Este deve ser configurado com uma lista de nomes de campos
que serão afetados pela busca, sempre que alguém submeter um texto por esta
caixa de texto.
Estes campos devem ser algum tipo de campo de texto, como CharField
ou
TextField
. Você pode também executar uma pesquisa relacionada a
ForeignKey
com a lookup API “siga” a notação:
search_fields = ['foreign_key__related_fieldname']
Quando alguém faz uma busca pelo admin, o Django divide a consulta em palavras e
retorna todos os objetos que contém cada uma das palavras, diferenciando
maiúsculas, onde pelo menos uma das palavras deve estar no search_fields
.
Por exemplo, se search_fields
é setado para ['first_name', 'last_name']
e um usuário procura por john lennon
, o Django fará o equivalente a esta
clausula SQL WHERE
:
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
Para buscas mais rápidas e/ou mais restritivas, prefixe o nome do campo com um operador:
^
Combina com o início do campo. Por exemplo, se
search_fields
é setado para['^first_name', '^last_name']
e um usuário procurar porjohn lennon
, o Django fará o equivalente a clausula SQLWHERE
:WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%') AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
Esta consulta é mais eficiente que a normal
'%john%'
, pois o banco de dados somente precisa checar o início dos dados da coluna, ao invés de procurar através de todo ele. Ainda mais, se a coluna tem um index nela, alguns bancos de dados podem ser capazes de usar o index para esta consulta, mesmo sendo uma consultaLIKE
.=
Combina exatamente, não diferencia maiúsculas. Por exemplo, se
search_fields
for configurado para['=first_name', '=last_name']
e um usuário procura porjohn lennon
, o Django fará o equivalente a clausula SQLWHERE
:WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john') AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')
Note que a entrada da consulta é dividida nos espaços, então, seguindo este exemplo, atualmente não é possível procurar por todos os dados em que
first_name
é exatamente'john winston'
(contendo espaço).@
- Executa uma combinação full-text. Essa é como o método de procura padrão, mas usa um index. Atualmente isso só está desponível para MySQL.
-
ModelAdmin.
change_list_template
¶
Caminho para um template personalizado que será usado pelos objetos model na visão de “listagem”. Os templates podem sobrescrever ou extender os templates de base do admin como descrito em Sobrescrevendo Templates do Admin.
Se você não especificar este atributo, um template padrão é entregue com o Django que fornece a aparência padrão do admin.
-
ModelAdmin.
change_form_template
¶
Caminho para o template personalizado que será usado na visão de criação e edição de um objeto model. Os templates podem sobrescrever ou extender os templates de base do admin como descrito em Sobrescrevendo Templates do Admin.
Se você não especificar este atributo, um template padrão é entregue com o Django que fornece a aparência padrão do admin.
-
ModelAdmin.
object_history_template
¶
Caminho para um template que será usado na visão de histórico do objeto model. Os templates podem sobrescrever ou extender os templates de base do admin como descrito em Sobrescrevendo Templates do Admin.
Se você não especificar este atributo, um template padrão é entregue com o Django que fornece a aparência padrão do admin.
-
ModelAdmin.
delete_confirmation_template
¶
Caminho para um template personalizado que será usado pela visão responsável por mostrar a confirmação de exclusão de um ou mais objetos. Os templates podem sobrescrever ou extender os templates de base do admin como descrito em Sobrescrevendo Templates do Admin.
Se você não especificar este atributo, um template padrão é entregue com o Django que fornece a aparência padrão do admin.
Métodos do ModelAdmin
¶
-
ModelAdmin.
save_model
(self, request, obj, form, change)¶
O método save_model
recebe o HttpRequest
, uma intância do model, uma
instância de ModelForm
e um valor booleano indicando se está adicionando ou
editando um objeto. Aqui você pode fazer quaisquer operações pré ou pós
salvamento.
Por exemplo, para atachar request.user
ao objeto antes de salvá-lo:
class ArticleAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = request.user
obj.save()
-
ModelAdmin.
save_formset
(self, request, form, formset, change)¶
O método save_formset
recebe o HttpRequest
, a instância do ModelForm
pai e um valor booleano que indica se está adicionando ou editando um objeto
pai.
Pro exemplo para atachar request.user
a cada instância de formset de
mudança:
class ArticleAdmin(admin.ModelAdmin):
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
instance.user = request.user
instance.save()
formset.save_m2m()
Outros métodos¶
-
ModelAdmin.
add_view
(self, request, form_url='', extra_context=None)¶
Um view do Django para a página de inclusão de instância de model. Veja a nota abaixo.
-
ModelAdmin.
change_view
(self, request, object_id, extra_context=None)¶
Um view do Django para a página de edição de instância de model. Veja nota abaixo.
-
ModelAdmin.
changelist_view
(self, request, extra_context=None)¶
Um view do Django para página de listagem/ações de instância de model. Veja nota abaixo.
-
ModelAdmin.
delete_view
(self, request, object_id, extra_context=None)¶
Um view do Django para página de confirmação de exclusão de instância e model. Veja nota abaixo.
-
ModelAdmin.
history_view
(self, request, object_id, extra_context=None)¶
Um view do Django para a página que mostra o histórico de modificações de uma instância de model.
Diferentemente dos métodos tipo hook do ModelAdmin
detalhados na seção
anterior, estes cinco métodos são na verdade, projetados para serem invocados
como views do Django pelo URL dispatcher da aplicação admin que renderizam
páginas com instâncias de model para operações CRUD. Como resultado, a completa
sobrescrita destes métodos mudará o comportamento da aplicação admin.
Uma razão comum para sobrescrever estes métodos é para aumentar o contexto dos dados que são fornecidos para o template que renderiza o view. No exemplo a seguir, o view de edição é sobrescrito de modo que ao template renderizado é fornecido alguns dados extras que caso contrário não estariam disponíveis:
class MyModelAdmin(admin.ModelAdmin):
# Um template para um view bastante personalizada:
change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html'
def get_osm_info(self):
# ...
def change_view(self, request, object_id, extra_context=None):
my_context = {
'osm_data': self.get_osm_info(),
}
return super(MyModelAdmin, self).change_view(request, object_id,
extra_context=my_context)
Definições de mídia ModelAdmin
¶
Tem vezes em que você gostaria de adicionar um pouco de CSS e/ou JavaScript aos
views adicionar/editar. Isso pode ser realizado usando uma classe interna Media
no seu ModelAdmin
:
class ArticleAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ("my_styles.css",)
}
js = ("my_code.js",)
Tenha em mente que este será prefixado com MEDIA_URL
. A mesma regra se
aplica nas regras de definições de mídia em formulários.
Adicionando validação personalizada ao admin¶
Adicionando validação personalizada de dados no admin é bem simples. A interface
automática de administração reusa o django.forms
, e a classe
ModelAdmin
tem a mesma abilidade de definir seu próprio formulário:
class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm
O MyArticleAdminForm
pode ser definido em qualquer lugar dentro de seu
caminho de import. Agora com seu form você pode adicionar sua própria validação
para qualquer campo:
class MyArticleAdminForm(forms.ModelForm):
class Meta:
model = Article
def clean_name(self):
# faça algo que valide seus dados
return self.cleaned_data["name"]
É importante usar um ModelForm
aqui, caso contrário algo pode não funcionar.
Veja a documentação forms em valização
personalizada e, mais especificamente, o notas de
validação de formulários para mais
informações.
Objetos InlineModelAdmin
¶
A interface admin tem a abilidade de editar models na mesma página de um model pai. Este são chamados de inlines. Suponhamos que você tenha dois models:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=100)
Você pode editar os livros escritos por um autor na página do autor. Você pode
adicionar inlines ao seu model para especificá-los em um
ModelAdmin.inlines
:
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]
O Django fornece duas subclasses ao InlineModelAdmin
e elas são:
TabularInline
StackedInline
A diferença entre estas duas é meramente o template utilizado para renderizá-las.
Opções InlineModelAdmin
¶
A classe InilneModelAdmin
é uma subclasse de ModelAdmin
de modo que ele
herda todas as mesmas funcionalidades assim como as suas próprias:
model
¶
O model em que o inline é usado. Este é obrigatório.
fk_name
¶
O nome da chave estrangeira no model. Na maioria dos casos este será tratado
de forma automática, mas fk_name
deve ser especificada explicitamente se
houver mais de uma chave estrangeira para o mesmo model pai.
formset
¶
O padrão para BaseInlineFormSet
. Usar seu próprio formset pode dar a você
muitas possibilidades de personalização. Inlines são embutidos a volta de
model formsets.
form
¶
O valor para form
padrão para BaseModelForm
. Este é o que é passado
através do formset_factory
quando está criando o formset para este inline.
extra
¶
Este controla o número de formulários extra que um formset mostrará além dos formulário inciais. Veja a documentação dos formsets para mais informações.
max_num
¶
Este controla o número máximo de formulários que serão mostrados num inline. Este não é diretamente correlacionado ao número de objetos, mas pode ser se o valor for pequeno o suficiente. Veja Limitando o número de objetos editáveis para mais informações.
raw_id_fields
¶
Por padrão, o admin do Django usa um select-box (<select>) para campos que são
ForeignKey
. Algumas vezes você pode não desejar ficar sujeito a um overhead
ao selecionar todos as instâncias relacionadas num drop-down.
O raw_id_fields
é uma lista de campos que você gostaria de mudar dentro de
um widget Input
tanto para ForeignKey
quanto para ManuToManyField
:
class BookInline(admin.TabularInline):
model = Book
raw_id_fields = ("pages",)
template
¶
O template usado para renderizar o inline na página.
verbose_name
¶
Uma sobrescrita para verbose_name
encontrado na classe interna Meta
do
model.
verbose_name_plural
¶
Uma sobrescrita para o verbose_name_plural
encontrado na classe interna
Meta
do model.
Trabalhando com um model com duas ou mais chaves estrangeiras para o mesmo model pai¶
Algumas vezes é possível haver mais de uma chave estrangeira para o mesmo model. Vejamos esta instância de model:
class Friendship(models.Model):
to_person = models.ForeignKey(Person, related_name="friends")
from_person = models.ForeignKey(Person, related_name="from_friends")
Se você quiser mostrar um inline nas páginas adicionar/editar do admin para
Person
, você precisa explicitamente definir a chave primária, tendo em vista
que ele não consegue definir automáticamente:
class FriendshipInline(admin.TabularInline):
model = Friendship
fk_name = "to_person"
class PersonAdmin(admin.ModelAdmin):
inlines = [
FriendshipInline,
]
Trabalhando com Models Intermediários Many-to-Many¶
Por padrão, os widgets do admin para relações muito-para-muitos serão mostrados
inlines não importando qual model contém a referência atual para o
ManyToManyField
. No entanto, quando você especificar um model intermediário
usando o argumento through
para um ManyToManyField
, o admin não mostrará
o widget por padrão. Isso porque cada instância de model intermediário requer
mais informações que poderiam ser mostradas num único widget, e o layout
requerido por vários widgets irão variar dependendo do model intermediário.
No entanto, nós ainda queremos ter a possibilidade de editar estar informações inline. Felizmente, isso é fácil de fazer com admin models inline. Suponhamos que temos os seguintes models:
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
O primeiro passo em mostrar este model intermediário no admin é definir uma
classe inline para o model Membership
:
class MembershipInline(admin.TabularInline):
model = Membership
extra = 1
Este exemplo simples usa o valor padrão InlineModelAdmin
para o model
Membership
, e limita os formulários adicionais para um. Isso poderia ser
personalizado usando qualquer uma das opções disponíveis para classes
InlineModelAdmin
.
Agora crie visões no admin para os models Person
e Group
:
class PersonAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
class GroupAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
Finalmente, registre seus models Person
e Group
no site admin:
admin.site.register(Person, PersonAdmin)
admin.site.register(Group, GroupAdmin)
Agora seu site admin está configurado para editar objetos Membership
tanto
da página de detalhes do Person
quanto do Group
.
Usando relações genéricas como um inline¶
É possível usar um inline com objetos relacionados genericamente. Vamos dizer que você tenha os seguintes models:
class Image(models.Model):
image = models.ImageField(upload_to="images")
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey("content_type", "object_id")
class Product(models.Model):
name = models.CharField(max_length=100)
Se você quer permitir a edição e criação de instâncias Image
sobre
Product
você pode simplesmente usar GenericInlineModelAdmin
fornecido
pelo django.contrib.contenttypes.generic
. No seu admin.py
para esta
aplicação de exemplo:
from django.contrib import admin
from django.contrib.contenttypes import generic
from myproject.myapp.models import Image, Product
class ImageInline(generic.GenericTabularInline):
model = Image
class ProductAdmin(admin.ModelAdmin):
inlines = [
ImageInline,
]
admin.site.register(Product, ProductAdmin)
O django.contrib.contenttypes.generic
fornece ambos um
GenericTabularInline
e GenericStackedInline
e se comporta como qualquer
outro inline. Veja a documentação do contenttypes para informações mais específicas.
Sobrescrevendo Templates do Admin¶
É relativamente fácil sobrescrever a maior parte dos templates que o módulo de admin usa para gerar as várias páginas de um site admin. Você pode sobrescrever somente algumas partes desses templates para uma app específica, ou um model específico.
Configurando os diretórios de template do admin do seu projeto¶
Os arquivos de template do admin estão localizados no diretório
contrib/admin/templates/admin
.
A fim de sobrescrever um ou mais deles, primeiro crie um diretório admin
no
diretórios de templates do seu projeto. Este pode ser qualquer um dos diretórios
que você especificou no TEMPLATE_DIRS
.
Dentro deste diretório admin
, crie sub-diretórios com o nome de suas apps.
Dentro destes sub-diretórios crie sub-diretórios com o nome de seus models.
Perceba, que a aplicação admin procura por nomes de diretórios em minúsculo,
então esteja certo do nome deles está todo em minúsculo, caso você esteja
rodando sua aplicação num sistemas de arquivo case-sensitive.
Para sobrescrever um template do admin para uma app específica, copie e edite o
template do diretório django/contrib/admin/templates/admin
, e salve-o num
dos diretórios criados a pouco.
Por exemplo, se nós procurarmos adicionar uma ferramenta na visão de listagem
para todos os models de uma aplicação chamada my_app
, nós copiariámos
contrib/admin/templates/admin/change_list.html
para o diretório
templates/admin/my_app/
de seu projeto, e fariámos as mudanças necessárias.
Caso desejássemos adicionar uma ferramenta na visão de listagem somente para um
model específico chamado ‘Page’, nós poderiámos copiar aquele mesmo arquivo para
o diretório templates/admin/my_app/page
de seu projeto.
Sobrescrever vs. substituir um template do admin¶
Por causa do design modular dos templates do admin, geralmente é necessário, mas nem sempre aconselhável, substituir todo um template. É quase semper melhor sobrescrever somente a seção do template que precisa ser mudada.
Para continuar o exemplo acima, nós queremos adicionar um novo link próximo ao
History
para o model Page
. Depois de olhar no change_form.html
nós
determinamos que somente precisamos sobrescrever o bloco object-tools
.
Assim, aqui está o novo change_form.html
:
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block object-tools %}
{% if change %}{% if not is_popup %}
<ul class="object-tools">
<li><a href="history/" class="historylink">{% trans "History" %}</a></li>
<li><a href="mylink/" class="historylink">My Link</a></li>
{% if has_absolute_url %}
<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">
{% trans "View on site" %}</a>
</li>
{% endif%}
</ul>
{% endif %}{% endif %}
{% endblock %}
E era isso! Se nós colocarmos este arquivo no diretório
templates/admin/my_app
, nosso link apareceria em todos os formulários de
edição dos models.
Templates que podem ser sobrescritos por uma app ou model¶
Nem todo template em contrib/admin/templates/admin
pode ser sobrescrito por
app ou por model. Os seguintes podem:
change_form.html
change_list.html
delete_confirmation.html
object_history.html
Para a maioria dos templates que não são sobrescritos desta forma, você pode
ainda sobrescrevê-los pra o seu projeto inteiro. É só colocar uma nova versão
no seu diretório templates/admin
. Este é particularmente útil para criar
páginas de erro 404 e 500.
Note
Alguns dos templates do admin, como o change_list_request.html
são
usados para renderizar inclusion tags personalizadas. Estas podem ser
sobrescritas, mas em alguns casos provavelmente é melhor você criar sua
própria versão da tag em questão e dá-lhe um nome diferente. Desta forma
você pode usá-la seletivamente.
Template raiz e de login¶
Se você deseja mudar o template index ou de login, seria melhor você criar sua
própria instância de AdminSite
(veja abaixo), e mudar as propriedades
AdminSite.index_template
ou AdminSite.login_template
.
Objetos AdminSite
¶
Um site de administração do Django é representado por uma instância do
django.contrib.admin.sites.AdminSite
; por padrão, uma instância desta classe
é criada como django.contrib.admin.site
e você pode registrar seus models
e instâncias do modelAdmin
nele.
Se você gostaria de configurar de setar sua própria interface de administração
com comportamentos personalizados, contudo, você é livre para extender o
AdminSite
e sobrescrever ou adicionar qualquer coisa que queira. Então,
simplesmente crie uma instância de sua classe extendida do AdminSite
(da
mesma forma como você instancia qualquer outra classe Python), e registre seus
models e subclasses de ModelAdmin
com ele ao invés de usar o padrão.
Atributos do AdminSite
¶
-
AdminSite.
index_template
¶
Caminho para um template personalizado que será usado pela página principal do site de administração. Os templates podem sobrescrever ou extender os templates base do admin como descrito em Sobrescrevendo Templates do Admin.
-
AdminSite.
login_template
¶
Caminho para um templates personalizado que será usado pela página de login do site admin. Os templates podem sobrescrever ou extender os templates base do admin como descrito em Sobrescrevendo Templates do Admin.
Vinculando instâncias do AdminSite
ao seu URLconf¶
O último passo ao configurar o admin do Django é vincular o sua instância
AdminSite
dentro do seu URLconf. Faça isso apontando uma certa URL para o
método AdminSite.urls
.
Neste exemplo, nós registramos a instância padrão AdminSite
do
django.contrib.admin.site
na URL /admin
# urls.py
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
('^admin/(.*)', admin.site.root),
)
Acima nós usamos admin.autodiscover()
para automaticamente carregar os
módulos admin.py do INSTALLED_APPS
.
Neste exemplo, nós registramos a instância do AdminSite
myproject.admin.admin_site
na URL /myadmin/
# urls.py
from django.conf.urls.defaults import *
from myproject.admin import admin_site
urlpatterns = patterns('',
('^myadmin/(.*)', admin_site.root),
)
Realmente não há necessidade de usar o autodiscover quando estiver usando sua
própria instância do AdminSite
, tendo em vista que você provavelmente já
tenha importado todos os seus módulos admin.py das aplicações no seu módulo
myproject.admin
.
Note que a expressão regular no URLpattern deve agrupar tudo que vier após
a raiz da URL – por isso o (.*)
nestes exemplos.
Vários sites admin no mesmo URLconf¶
É fácil criar várias instâncias de admin no mesmo site feito em Django. É só
criar várias instâncias do AdminSite
e colocá-los em URLs diferentes.
Neste exemplo, as URLs /baisc-admin/
e /advanced-admin/
realçam versões
separadas do site admin – usando as instâncias do AdminSite
myproject.admin.basic_site
e myproject.admin.advanced_site
,
respectivamente:
# urls.py
from django.conf.urls.defaults import *
from myproject.admin import basic_site, advanced_site
urlpatterns = patterns('',
('^basic-admin/(.*)', basic_site.root),
('^advanced-admin/(.*)', advanced_site.root),
)