Dans admin, je voudrais désactiver un champ lors de la modification d'objet, mais le rendre obligatoire lors de l'ajout d'un nouvel objet.
Quelle est la façon dont Django aborde celui-ci?
Vous pouvez remplacer la méthode get_readonly_fields
de l'administrateur:
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
Si vous souhaitez définir tous les champs en lecture seule uniquement dans la vue Modification, remplacez le champ get_readonly_fields de l'administrateur:
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
Et si vous voulez masquer les boutons de sauvegarde en mode de modification :
Changer la vue
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)
Modifier les autorisations si l'utilisateur tente de modifier:
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
Cette solution a été testée sur Django 1.11
Pour votre information, si quelqu'un d'autre rencontre les deux mêmes problèmes que j'ai rencontrés:
Vous devez toujours déclarer en permanence les champs readonly_fields dans le corps de la classe, car l'attribut de la classe readonly_fields sera accessible à partir de la validation (voir Django.contrib.admin.validation: validate_base (), line.213 appx)
Cela ne fonctionnera pas avec Inlines car l'obj transmis à get_readonly_fields () est le parent obj (j'ai deux solutions plutôt hacky et basse sécurité utilisant css ou js)
Une variation basée sur l'excellente suggestion précédente de Bernhard Vallant, qui préserve également toute personnalisation possible fournie par la classe de base (le cas échéant):
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
Vous avez un problème similaire. Je l'ai résolu avec "add_fieldsets" et "restricted_fieldsets" dans ModelAdmin.
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', )}),
)
Veuillez consulter, par exemple: http://code.djangoproject.com/svn/Django/trunk/Django/contrib/auth/admin.py
Mais cela ne protège pas votre modèle contre les modifications ultérieures de "add_objX" . Si vous le souhaitez également, je pense que vous devez passer en revue la fonction "enregistrer" de la classe Model et vérifier ses modifications.
Voir: www.djangoproject.com/documentation/models/save_delete_hooks/
Greez, Nick
Vous pouvez le faire en remplaçant la méthode formfield_for_foreignkey de ModelAdmin:
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)