Frage

ich folgende Admin-Setup haben, so dass ich hinzufügen / bearbeiten Sie einen Benutzer und sein Profil zugleich.

class ProfileInline(admin.StackedInline):
    """
    Allows profile to be added when creating user
    """
    model = Profile


class UserProfileAdmin(admin.ModelAdmin):
    """
    Options for the admin interface
    """
    inlines = [ProfileInline]
    list_display = ['edit_obj', 'name', 'username', 'email', 'is_active',
        'last_login', 'delete_obj']
    list_display_links = ['username']
    list_filter = ['is_active']
    fieldsets = (
        (None, {
            'fields': ('first_name', 'last_name', 'email', 'username',
                'is_active', 'is_superuser')}),
        )
    ordering = ['last_name', 'first_name']
    search_fields = ['first_name', 'last_name']

admin.site.register(User, UserProfileAdmin)

Das Problem ist, ich brauche zwei der Felder im Profil Inline-Form benötigt werden, wenn der Benutzer das Hinzufügen. Die Inline-Form überprüft nicht, es sei denn Eingang eingegeben wird. Gibt es trotzdem, die Inline erforderlich zu machen, so dass es nicht leer gelassen werden kann?

War es hilfreich?

Lösung

Ich nahm Carl Rat und machte eine viel bessere Umsetzung dann den Hack-ish, die ich auf seine Antwort in meinem Kommentar erwähnt. Hier ist meine Lösung:

Aus meiner forms.py:

from django.forms.models import BaseInlineFormSet


class RequiredInlineFormSet(BaseInlineFormSet):
    """
    Generates an inline formset that is required
    """

    def _construct_form(self, i, **kwargs):
        """
        Override the method to change the form attribute empty_permitted
        """
        form = super(RequiredInlineFormSet, self)._construct_form(i, **kwargs)
        form.empty_permitted = False
        return form

Und die admin.py

class ProfileInline(admin.StackedInline):
    """
    Allows profile to be added when creating user
    """
    model = Profile
    extra = 1
    max_num = 1
    formset = RequiredInlineFormSet


class UserProfileAdmin(admin.ModelAdmin):
    """
    Options for the admin interface
    """
    inlines = [ProfileInline]
    list_display = ['edit_obj', 'name', 'username', 'email', 'is_active',
        'last_login', 'delete_obj']
    list_display_links = ['username']
    list_filter = ['is_active']
    fieldsets = (
        (None, {
            'fields': ('first_name', 'last_name', 'email', 'username',
                'is_active', 'is_superuser')}),
        (('Groups'), {'fields': ('groups', )}),
    )
    ordering = ['last_name', 'first_name']
    search_fields = ['first_name', 'last_name']


admin.site.register(User, UserProfileAdmin)

Das ist genau das, was ich will, es macht das Profil Inline formset Validieren. Also da gibt es Felder in der Profilform erforderlich sind, wird es bestätigen und fehlschlagen, wenn die erforderlichen Informationen nicht auf dem Inline-Formular eingegeben werden.

Andere Tipps

Jetzt mit Django 1.7 können Sie Parameter min_num verwenden. Sie haben keine Klasse RequiredInlineFormSet mehr benötigen.

Siehe https://docs.djangoproject.com /en/1.8/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.min_num

class ProfileInline(admin.StackedInline):
    """
    Allows profile to be added when creating user
    """
    model = Profile
    extra = 1
    max_num = 1
    min_num = 1 # new in Django 1.7


class UserProfileAdmin(admin.ModelAdmin):
    """
    Options for the admin interface
    """
    inlines = [ProfileInline]
    ...


admin.site.register(User, UserProfileAdmin)

Sie können dies wahrscheinlich tun, aber Sie werden Ihre Hände schmutzig in dem formset / Inline-Code bekommen.

Zunächst einmal, ich glaube, Sie wollen es immer eine Form in der formset in diesem Fall sein, und nie mehr als ein, so dass Sie setzen wollen? MAX_NUM = 1 und Extra = 1 in Ihrem ProfileInline.

Ihr Kernproblem ist, dass BaseFormSet._construct_form geht empty_permitted = True zu jeder "extra" (dh leer) Form in der formset. Dieser Parameter teilt das Formularvalidierung, wenn seine unverändert zu umgehen. Sie müssen nur einen Weg finden, empty_permitted = False für das Formular festgelegt.

Sie können verwenden rel="noreferrer"> in Ihrem inline, hilft das könnte so. Bemerken, dass _construct_form nimmt ** kwargs und ermöglicht es, dass die kwargs die einzelnen Formularinstanzen weitergegeben außer Kraft zu setzen, Sie _construct_forms in Ihrer Formset Unterklasse außer Kraft setzen könnten und es hat Pass empty_permitted = False in jedem Aufruf _construct_form. Der Nachteil ist, dass Sie auf interne APIs angewiesen sind (und man müßte _construct_forms neu zu schreiben).

Alternativ könnten Sie versuchen, die get_formset Methode auf Ihrem ProfileInline überschreiben, und nach den Eltern get_formset Aufruf steckt manuell an der Form innerhalb des zurück formset:

def get_formset(self, request, obj=None, **kwargs):
    formset = super(ProfileInline, self).get_formset(request, obj, **kwargs)
    formset.forms[0].empty_permitted = False
    return formset

Spielen Sie herum und sehen, was Sie zur Arbeit machen!

Sie müssen auf min_num in Inline- und validate_min in formset.

https://docs.djangoproject.com/ de / 1.8 / Themen / Formulare / Formularsätze / # validate-min

class SomeInline(admin.TabularInline):
    ...
    min_num = 1

    def get_formset(self, request, obj=None, **kwargs):
        formset = super().get_formset(request, obj=None, **kwargs)
        formset.validate_min = True
        return formset
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top