Přidáváme objekt alá User
Všimli jste si někdy, že přidání nového uživatele v administračním rozhraní Djanga probíhá trochu jinak, než přidání jakéhokoliv jiného objektu?
Pro připomenutí — nový uživatel se zadává prostřednictvím dvou po sobě navazujících formulářů, kdy v první fázi vyplníte pouze username a heslo, a teprve při druhém kroku je možné doplnit zbytek informací.
Potřeboval jsem vytvořit podobné workflow a po nakouknutí do zdrojáku Djanga mě opět překvapilo, jak jednoduše je možné podobného efektu dosáhnout. Proměte si prsty, jdeme na to.
Do administrační třídy si přidejte 3 nové atributy:
class MenuAdmin(admin.ModelAdmin):
add_form = MenuAdminAddForm
add_fieldsets = (
(None, {
'fields': ('system_name', 'name')}
),
)
add_form_template = 'admin/menu/menu/add_form.html'
Atribut add_form definuje formulářovou třídu, která bude použita pouze při vytváření nového objektu (do atributu form můžete klíďo-píďo uvést jiný formík, který bude použitý při editaci existujícího záznamu). Atribut add_fieldsets definuje seznam položek z add_form, které se na admin stránce zobrazí. A konečně add_form_template říká, že pro vykreslení stránky bude použita uvedená (mírně upravená) šablona.
Modří už tuší, že tohle stačit nebude. Django o žádných add_* atributech nemá ani páru. Musíme mu proto lehulince pomoct. Do admin třídy doplňte metodu:
def get_form(self, request, obj=None, **kwargs):
defaults = {}
if obj is None:
defaults.update({
'form': self.add_form,
'fields': admin.util.flatten_fieldsets(self.add_fieldsets),
})
defaults.update(kwargs)
return super(MenuAdmin, self).get_form(request, obj, **defaults)
Metoda get_form dokáže rozpoznat jestli se přidává nový objekt, a v tomto připadku upraví argumenty pro rodičovský get_form tak, aby namísto obvyklého form a fieldsets použila add_form a add_fieldsets. Pokud by došlo k editaci existujícího objektu, Django se bude chovat standardně, tj. použije atribut form a fieldsets (více viz oficiální dokumentace).
A k čemu ten add_form_template? Ten pouze přidá do formuláře informativní hlášku o tom, že po vytvoření objektu bude uživateli nabídnut bohatší formulář s doplňujícími informacemi:
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block form_top %}
<p>{% trans "First, enter a username and password.
Then, you'll be able to edit more user options." %}</p>
<input type="hidden" name="_continue" value="1" />
{% endblock %}
Vtipný kvíz na konec: víte jakou roli má hidden input _continue?
(není tam náhodou)