webentwicklung-frage-antwort-db.com.de

django admin macht ein Feld schreibgeschützt, wenn Sie obj ändern, aber beim Hinzufügen eines neuen obj

In admin möchte ich ein Feld beim Ändern eines Objekts deaktivieren, es aber machen, wenn ein neues Objekt hinzugefügt wird.

Was ist der Django-Weg, um über diesen zu gehen?

70
frnhr

Sie können die get_readonly_fields-Methode des Administrators überschreiben:

class MyModelAdmin(admin.ModelAdmin):

    def get_readonly_fields(self, request, obj=None):
        if obj: # editing an existing object
            return self.readonly_fields + ('field1', 'field2')
        return self.readonly_fields
141

Wenn Sie Alle Felder als schreibgeschützt festlegen nur in der Änderungsansicht festlegen möchten, überschreiben Sie die get_readonly_fields des Administrators:

def get_readonly_fields(self, request, obj=None):
    if obj: # editing an existing object
        # All model fields as read_only
        return self.readonly_fields + Tuple([item.name for item in obj._meta.fields])
    return self.readonly_fields

Und wenn Sie die Schaltflächen zum Speichern in der Änderungsansicht ausblenden möchten:

  1. Ändern Sie die Ansicht

    def change_view(self, request, object_id, form_url='', extra_context=None):
        ''' customize edit form '''
        extra_context = extra_context or {}
        extra_context['show_save_and_continue'] = False
        extra_context['show_save'] = False
        extra_context['show_save_and_add_another'] = False # this not works if has_add_permision is True
        return super(TransferAdmin, self).change_view(request, object_id, extra_context=extra_context)
    
  2. Ändern Sie die Berechtigungen, wenn der Benutzer versucht, zu bearbeiten:

    def has_add_permission(self, request, obj=None):
       # Not too much elegant but works to hide show_save_and_add_another button
        if '/change/' in str(request):
            return False
        return True
    

    Diese Lösung wurde über Django 1.11 getestet.

9
DVicenteR

Zu Ihrer Information: falls jemand anderes auf die gleichen zwei Probleme stößt wie ich:

  1. Sie sollten dennoch dauerhaft readonly_fields im Body der Klasse deklarieren, da auf das Klassenattribut readonly_fields von der Validierung aus zugegriffen wird (siehe Django.contrib.admin.validation: validate_base (), line.213 appx).

  2. Dies funktioniert nicht mit Inlines, da das an get_readonly_fields () übergebene Objekt das übergeordnete Objekt ist (ich habe zwei ziemlich hackige und wenig sichere Lösungen, die css oder js verwenden).

3
Tim Diggins

Eine Variation, die auf dem vorherigen ausgezeichneten Vorschlag von Bernhard Vallant basiert, wobei auch eventuelle Anpassungen der Basisklasse (falls vorhanden) erhalten bleiben:

class MyModelAdmin(BaseModelAdmin):

    def get_readonly_fields(self, request, obj=None):
        readonly_fields = super(MyModelAdmin, self).get_readonly_fields(request, obj)
        if obj: # editing an existing object
            return readonly_fields + ['field1', ..]
        return readonly_fields
1
Mario Orlandi

Ich habe ein ähnliches Problem. Ich habe es mit "add_fieldsets" und "restricted_fieldsets" in ModelAdmin gelöst.

from Django.contrib import admin  
class MyAdmin(admin.ModelAdmin):
 declared_fieldsets = None
 restricted_fieldsets = (
    (None, {'fields': ('mod_obj1', 'mod_obj2')}),
    ( 'Text', {'fields': ('mod_obj3', 'mod_obj4',)}),
 )

 add_fieldsets = (
            (None, {
             'classes': ('wide',),
             'fields': ('add_obj1', 'add_obj2', )}),
             )

Siehe z. B .: http://code.djangoproject.com/svn/Django/trunk/Django/contrib/auth/admin.py

Dies schützt Ihr Modell jedoch nicht vor späteren Änderungen von "add_objX" . Wenn Sie dies ebenfalls wünschen, müssen Sie die Modellklassenfunktion "Speichern" verwenden und dort nach Änderungen suchen.

Siehe: www.djangoproject.com/documentation/models/save_delete_hooks/

Greez, Nick

0
Nick Ma.

Sie können dies tun, indem Sie die formfield_for_foreignkey-Methode von ModelAdmin überschreiben:

from Django import forms
from Django.contrib import admin

from yourproject.yourapp.models import YourModel

class YourModelAdmin(admin.ModelAdmin):

    class Meta:
        model = YourModel

    def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
        # Name of your field here
        if db_field.name == 'add_only':
            if request:
                add_opts = (self._meta.app_label, self._meta.module_name)
                add = u'/admin/%s/%s/add/' % add_opts
                if request.META['PATH_INFO'] == add:
                    field = db_field.formfield(**kwargs)
                else:
                    kwargs['widget'] = forms.HiddenInput()
                    field = db_field.formfield(**kwargs)
            return field
        return admin.ModelAdmin(self, db_field, request, **kwargs)
0
David Miller