Lägga till extra fält i Django admin

Admin-applikationen till Django är fantastisk på många sätt. Just att modellerna man har i Django speglas direkt i ett webbgränssnitt utan i princip någon egen insats är inte bara tidsbesparande utan det blir även ren och fin kod.

Det finns däremot situationer när man vill ha ett extra fält för att göra någon inställning.

Man kanske behöver ett fält som inte finns med i modellen och som inte ska lagras i databasen, men som t.ex. triggar någon annan händelse. Ett sådant fält kan man få genom att lägga in ett extra form i admin-klassen.

Om du tänker dig att du har en modell som heter Domain. Det är en modell som håller reda på domännamn. När du skapar eller ändrar ett domännamn så vill du kanske lägga till några fördefinierade mallar (template). Det kan vara t.ex. ett par epost-servrar eller liknande. Vilken mall du lägger till behövs inte sparas i själva Domain-modellen, det är ju oväsentligt. Däremot så vill man kunna välja vilken mall man använda när man skapar en ny domän i admin-gränssnittet. När sedan domänen sparas så kollar admin-gränssmittet vilken mall man valde och exekverar sedan en funktion från mall-objektet.

Här kommer ett exempel:

from django.contrib import admin
from django import forms

class DomainAdminForm(forms.ModelForm):
    templates = forms.ModelMultipleChoiceField(DomainTemplate.objects.order_by("name"), help_text = "Templates to apply", required=False)

    class Meta:
        model = Domain

    def save(self, commit=True):
        model = super(DomainAdminForm, self).save(commit=False)

        # if create (id not exists), save first
        if not model.id:
            model.save()

        # Apply template to domain
        for template in self.cleaned_data['templates']:
            template.apply(model)
        return model

class DomainAdmin(admin.ModelAdmin):
    list_display = ('name', 'type', 'serial')
    readonly_fields = ['serial']
    inlines = [RecordInline]

    form = DomainAdminForm

Klassen DomainAdminForm är ett form som lägger till ett MultipleChoice-fält som baseras på innehållet från DomainTemplate-modellen. I admin-klassen DomainAdmin anges att form = DomainAdminForm som pekar ut vilket extra formulär som ska användas.

När man sparar Domain-modellen så kommer alltså save-funktionen i DomainAdminForm att köras och här itereras alla angivna templates vars apply-funktion anropas.

Bilden nedan visar det nya form-fältet templates.