Yönetici olarak, nesneyi değiştirirken bir alanı devre dışı bırakmak istiyorum, ancak yeni nesne eklerken bunu zorunlu kılmak istiyorum.
Bunun için django'nun yolu nedir?
Yanıtlar:
Yöneticinin get_readonly_fields
yöntemini geçersiz kılabilirsiniz :
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
Tüm alanları sadece değişiklik görünümünde salt okunur olarak ayarlamak istiyorsanız , yöneticinin get_readonly_fields değerini geçersiz kılın:
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
Ve değişikliğin görünümünde düğmeler tasarruf postu istiyorsanız :
Görünümü değiştir
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)
Kullanıcı düzenlemeye çalışıyorsa izinleri değiştirin:
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
Bu çözüm Django 1.11 üzerinde test edilmiştir.
Bilginize: Karşılaştığım aynı iki sorunla başka birinin karşılaşması durumunda:
Readonly_fields sınıf özniteliğine doğrulamadan erişilebileceğinden, yine de sınıfın gövdesinde kalıcı olarak salt okunur alanları bildirmelisiniz (bkz. Django.contrib.admin.validation: validate_base (), satır.213 appx)
Get_readonly_fields () 'a iletilen nesne ana nesne olduğu için bu, Inlines ile çalışmaz (css veya js kullanan oldukça hacky ve düşük güvenlikli çözümüm var)
Bernhard Vallant'ın önceki mükemmel önerisine dayanan bir varyasyon, aynı zamanda temel sınıf tarafından sağlanan olası özelleştirmeleri de (varsa) korur:
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
Satır içi formlarla ilgili durum, Django 2.2.x için hala sabit değil, ancak John'un çözümü aslında oldukça akıllı.
Kod biraz durumuma göre ayarlanmış:
class NoteListInline(admin.TabularInline):
""" Notes list, readonly """
model = Note
verbose_name = _('Note')
verbose_name_plural = _('Notes')
extra = 0
fields = ('note', 'created_at')
readonly_fields = ('note', 'created_at')
def has_add_permission(self, request, obj=None):
""" Only add notes through AddInline """
return False
class NoteAddInline(admin.StackedInline):
""" Notes edit field """
model = Note
verbose_name = _('Note')
verbose_name_plural = _('Notes')
extra = 1
fields = ('note',)
can_delete = False
def get_queryset(self, request):
queryset = super().get_queryset(request)
return queryset.none() # no existing records will appear
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
# ...
inlines = (NoteListInline, NoteAddInline)
# ...
Bunu, ModelAdmin'in formfield_for_foreignkey yöntemini geçersiz kılarak yapabilirsiniz:
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)
Benzer bir sorun var. Bunu ModelAdmin'de "add_fieldsets" ve "restricted_fieldsets" ile çözdüm.
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', )}),
)
Lütfen örneğin bkz: http://code.djangoproject.com/svn/django/trunk/django/contrib/auth/admin.py
Ancak bu, modelinizi daha sonraki "add_objX" değişikliklerinden korumaz. Bunu da istiyorsanız, Model sınıfı "kaydetme" işlevini aşmanız ve oradaki değişiklikleri kontrol etmeniz gerektiğini düşünüyorum.
Bakınız: www.djangoproject.com/documentation/models/save_delete_hooks/
Selam, Nick