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)

Blog comments powered by Disqus