28 Stimmen

Dynamische Felder im Django-Admin

Ich möchte zusätzliche Felder zum Wert eines Feldes haben. Deshalb habe ich ein benutzerdefiniertes Admin-Formular erstellt, um einige neue Felder hinzuzufügen.

Bezogen auf den Blogbeitrag von Jacobian 1 ist dies, was ich gemacht habe:

class ProductAdminForm(forms.ModelForm):
    class Meta:
        model = Product

    def __init__(self, *args, **kwargs):
        super(ProductAdminForm, self).__init__(*args, **kwargs)
        self.fields['foo'] = forms.IntegerField(label="foo")

class ProductAdmin(admin.ModelAdmin):
    form = ProductAdminForm

admin.site.register(Product, ProductAdmin)

Aber das zusätzliche Feld 'foo' erscheint nicht im Adminbereich. Wenn ich das Feld so hinzufüge, funktioniert alles gut, ist aber nicht so dynamisch wie erforderlich, um die Felder entsprechend dem Wert eines anderen Feldes des Modells hinzuzufügen

class ProductAdminForm(forms.ModelForm):

    foo = forms.IntegerField(label="foo")

    class Meta:
        model = Product

class ProductAdmin(admin.ModelAdmin):
    form = ProductAdminForm

admin.site.register(Product, ProductAdmin)

Gibt es also eine Initialisierungsmethode, die ich erneut auslösen muss, um das neue Feld zum Laufen zu bringen? Oder gibt es einen anderen Ansatz?

5voto

santhoshnsscoe Punkte 199

Sie können dynamische Felder und Fieldset mit der Form-Metaklasse erstellen. Der untenstehende Beispielcode zeigt dies. Fügen Sie die Schleifenlogik gemäß Ihren Anforderungen hinzu.

class CustomAdminFormMetaClass(ModelFormMetaclass):
    """
    Metaklasse für benutzerdefiniertes Admin-Formular mit dynamischem Feld
    """
    def __new__(cls, name, bases, attrs):
        for field in get_dynamic_fields: #Logik zum Abrufen der Felder hinzufügen
            attrs[field] = forms.CharField(max_length=30) #Logik zum Hinzufügen des Formularfeldes
        return super(CustomAdminFormMetaClass, cls).__new__(cls, name, bases, attrs)

class CustomAdminForm(six.with_metaclass(CustomAdminFormMetaClass, forms.ModelForm)):
    """
    Benutzerdefiniertes Admin-Formular
    """

    class Meta:
        model = ModelName
        fields = "__all__" 

class CustomAdmin(admin.ModelAdmin):
    """
    Benutzerdefinierter Administrator 
    """

    fieldsets = None
    form = CustomAdminForm

    def get_fieldsets(self, request, obj=None):
        """
        Unterschiedliches Fieldset für das Admin-Formular
        """
        self.fieldsets = self.dynamic_fieldset(). #Logik zum Hinzufügen des dynamischen Fieldset mit Feldern
        return super(CustomAdmin, self).get_fieldsets(request, obj)

    def dynamic_fieldset(self):
        """
        Erhalte die dynamischen Fieldsets
        """
        fieldsets = []
        for group in get_field_set_groups: #Logik zum Abrufen der Felset-Gruppe
            fields = []
            for field in get_group_fields: #Logik zum Abrufen der Gruppenfelder
                fields.append(field)

            fieldset_values = {"fields": tuple(fields), "classes": ['collapse']}
            fieldsets.append((group, fieldset_values))

        fieldsets = tuple(fieldsets)

        return fieldsets

3voto

rhoerbe Punkte 433

Stephans Antwort ist elegant, aber als ich sie in dj1.6 verwendet habe, musste das Feld ein Tupel sein. Die vollständige Lösung sah so aus:

class ProductForm(ModelForm):
    foo = CharField(label='foo')

class ProductAdmin(admin.ModelAdmin):
    form = ProductForm
    def get_fieldsets(self, request, obj=None):
        fieldsets = super(ProductAdmin, self).get_fieldsets(request, obj)
        fieldsets[0][1]['fields'] += ('foo', ) 
        return fieldsets

0voto

second Punkte 26650

Ich bin mir nicht sicher, warum das nicht funktioniert, aber könnte ein möglicher Workaround sein, das Feld statisch zu definieren (im Formular) und es dann im __init__ zu überschreiben?

0voto

Alex Punkte 37

Ich konnte lange Zeit ein Problem mit der dynamischen Hinzufügung von Feldern nicht lösen. Die Lösung "little_birdie" funktioniert wirklich. Danke Birdie)) Die einzige Nuance ist: "Self.declared_fieldsets" sollte durch "self.fieldsets" ersetzt werden.

#kwargs['fields'] =  flatten_fieldsets(self.declared_fieldsets)
kwargs['fields'] =  flatten_fieldsets(self.fieldsets)

Ich habe Version 1.10 verwendet. Vielleicht hat sich etwas geändert.

Wenn jemand eine noch einfachere und elegantere Lösung findet, zeigt sie hier.

Danke an alle )))

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X