django admin एक फ़ील्ड रीड-ओनली करता है, जब ओबीज को संशोधित करता है, लेकिन नए ओज को जोड़ते समय आवश्यक होता है


91

व्यवस्थापक में, मैं ऑब्जेक्ट को संशोधित करते समय किसी फ़ील्ड को अक्षम करना चाहूंगा, लेकिन नई ऑब्जेक्ट जोड़ते समय इसे आवश्यक कर दूंगा।

इस बारे में जाने के लिए django तरीका क्या है?

जवाबों:


176

आप व्यवस्थापक की get_readonly_fieldsविधि को ओवरराइड कर सकते हैं :

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

21
लघु / प्रमुख चेतावनी: यह inlines के लिए काम नहीं करता है। डायनामिक "एक और एक्स जोड़ें" बटन रीडऑनली फ़ील्ड को "(कोई नहीं)" के रूप में दिखाता है, एक फॉर्म फ़ील्ड नहीं जैसा कि आप अपेक्षा करते हैं।
सेरिन

17

यदि आप सभी फ़ील्ड केवल परिवर्तन दृश्य पर पढ़े गए के रूप में सेट करना चाहते हैं , तो व्यवस्थापक के get_readonly_fields को ओवरराइड करें:

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

और यदि आप परिवर्तन दृश्य पर सहेजें बटन छिपाना चाहते हैं :

  1. नजरिया बदलो

    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. यदि उपयोगकर्ता संपादित करने का प्रयास कर रहे हैं तो अनुमतियाँ बदलें:

    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
    

    इस समाधान का परीक्षण Django 1.11 पर किया गया है


उत्तम। मुझे ठीक इसी की आवश्यकता थी!
वॉग्सलैंड

3

FYI करें: यदि कोई अन्य दो समस्याओं का सामना करता है तो मैं उसी में भाग लेता हूं:

  1. आपको अभी भी कक्षा के शरीर में किसी भी स्थायी रूप से readonly_fields घोषित करना चाहिए, क्योंकि readonly_fields वर्ग विशेषता सत्यापन से एक्सेस की जाएगी (देखें django.contrib.admin.validation: validate_fase) (line.213 appx)

  2. यह इनलाइन के साथ काम नहीं करेगा क्योंकि obj को get_readonly_fields () पेरेंट obj पास किया गया है (मेरे पास दो नहीं बल्कि हैसी और सीएसएस या js का उपयोग करते हुए कम-सुरक्षा समाधान हैं)


2
2. बिंदु - यह व्यवस्थापक में एक बग के कारण है: # 15602 ऐसा लगता है कि यह जल्द ही (अंतिम गतिविधि 2 साल पहले) तय नहीं किया जाएगा, इसलिए ऐसा लगता है कि हम सीएसएस / जेएस समाधान तक छोड़ दिए गए हैं।

2

बर्नहार्ड वालेंट के पिछले उत्कृष्ट सुझाव के आधार पर भिन्नता, जो आधार वर्ग द्वारा प्रदान किए गए किसी भी संभावित अनुकूलन को संरक्षित करता है (यदि कोई हो):

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

2

इनलाइन फॉर्म के साथ स्थिति अभी भी Django 2.2.x के लिए तय नहीं है, लेकिन जॉन से समाधान वास्तव में बहुत स्मार्ट है।

कोड मेरी स्थिति से थोड़ा सा जुड़ा:

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)
    # ...

0

आप ModelAdmin के formfield_for_foreignkey विधि को ओवरराइड करके ऐसा कर सकते हैं:

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

एक समान समस्या है। मैंने इसे ModelAdmin में "add_fieldsets" और "प्रतिबंधित_fieldsets" के साथ हल किया।

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', )}),
             )

कृपया देखें जैसे: http://code.djangoproject.com/svn/django/trunk/django/contrib/auth/admin.py

लेकिन यह आपके मॉडल को "add_objX" के बाद के परिवर्तनों से बचाता नहीं है। अगर आप भी यही चाहते हैं, तो मुझे लगता है कि आपको मॉडल क्लास "सेव" फंक्शन पर जाना होगा और वहां बदलावों की जांच करनी होगी।

देखें: www.djangoproject.com/documentation/models/save_delete_hooks/

ग्रीज, निक

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.