Django व्यवस्थापक इंटरफ़ेस में Readonly मॉडल?


86

मैं किसी मॉडल को पूरी तरह से केवल-व्यवस्थापक इंटरफ़ेस में कैसे पढ़ सकता हूं? यह एक तरह की लॉग टेबल के लिए है, जहाँ मैं एडमिन फीचर्स का उपयोग सर्च, सॉर्ट, फिल्टर आदि के लिए कर रहा हूँ, लेकिन लॉग को संशोधित करने की कोई आवश्यकता नहीं है।

यदि यह एक डुप्लिकेट की तरह दिखता है, तो यहां ऐसा नहीं है जो मैं करने की कोशिश कर रहा हूं:

  • मैं आसानी से खेतों की तलाश नहीं कर रहा हूं (यहां तक ​​कि हर क्षेत्र को आसानी से बनाने के बाद भी आप नए रिकॉर्ड बना पाएंगे)
  • मैं आसानी से एक उपयोगकर्ता बनाने के लिए नहीं देख रहा हूँ : प्रत्येक उपयोगकर्ता को आसानी से पढ़ा जाना चाहिए।

2
यह सुविधा जल्द ही आनी चाहिए: github.com/django/django/pull/5297
Bosco

2
has_view_permissionअंततः Django 2.1 में लागू किया गया था। इसके अलावा नीचे stackoverflow.com/a/51641149 देखें।
djvg

जवाबों:


21

Https://djangosnippets.org/snippets/10539/ देखें

class ReadOnlyAdminMixin(object):
    """Disables all editing capabilities."""
    change_form_template = "admin/view.html"

    def __init__(self, *args, **kwargs):
        super(ReadOnlyAdminMixin, self).__init__(*args, **kwargs)
        self.readonly_fields = self.model._meta.get_all_field_names()

    def get_actions(self, request):
        actions = super(ReadOnlyAdminMixin, self).get_actions(request)
        del_action = "delete_selected"
        if del_action in actions:
            del actions[del_action]
        return actions

    def has_add_permission(self, request):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

    def save_model(self, request, obj, form, change):
        pass

    def delete_model(self, request, obj):
        pass

    def save_related(self, request, form, formsets, change):
        pass

टेम्पलेट्स / व्यवस्थापक / view.html

{% extends "admin/change_form.html" %}
{% load i18n %}

{% block submit_buttons_bottom %}
  <div class="submit-row">
    <a href="../">{% blocktrans %}Back to list{% endblocktrans %}</a>
  </div>
{% endblock %}

टेम्पलेट्स / व्यवस्थापक / view.html (ग्रेपेली के लिए)

{% extends "admin/change_form.html" %}
{% load i18n %}

{% block submit_buttons_bottom %}
  <footer class="grp-module grp-submit-row grp-fixed-footer">
    <header style="display:none"><h1>{% trans "submit options"|capfirst context "heading" %}</h1></header>
    <ul>
       <li><a href="../" class="grp-button grp-default">{% blocktrans %}Back to list{% endblocktrans %}</a></li>
    </ul>
  </footer>
{% endblock %}

वैध लगता है। जब से मैंने Django का उपयोग किया है तब से यह बहुत लंबा है, यह देखने के लिए इंतजार कर सकता है कि अन्य टिप्पणीकारों को क्या कहना है।
स्टीव बेनेट

क्या यह Modelया के लिए एक मिश्रण है ModelAdmin?
ऑरेंजडॉग

इसके लिए है ModelAdmin
पास्कल पोलीयूनस

Django 1.8 के लिए और बाद में, get_all_field_names को हटा दिया गया है। उन्हें प्राप्त करने के लिए पीछे संगत तरीका हैउन्हें पाने का छोटा रास्ता
fzzylogic

आप has_add_permission
rluts

70

व्यवस्थापक संपादन के लिए है, न कि केवल देखने के लिए (आपको "दृश्य" अनुमति नहीं मिलेगी)। आप जो चाहते हैं उसे प्राप्त करने के लिए आपको जोड़ने, हटाने और सभी क्षेत्रों को आसानी से बनाने से मना करना होगा:

class MyAdmin(ModelAdmin):

    def has_add_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

(यदि आप बदलते हुए मना करते हैं तो आपको ऑब्जेक्ट देखने को भी नहीं मिलेगा)

कुछ अनकही कोड के लिए जो सभी क्षेत्रों को स्वचालित रूप से सेट करने की कोशिश करता है केवल-पढ़े जाने वाले मॉडल के रूप में मेरा उत्तर केवल-पढ़ने के लिए देखें

संपादित करें: यह भी अप्रयुक्त है, लेकिन सिर्फ मेरे LogEntryAdmin पर एक नज़र थी और यह है

readonly_fields = MyModel._meta.get_all_field_names()

नहीं पता है कि सभी मामलों में काम करेगा।

संपादित करें: QuerySet.delete () अभी भी वस्तुओं को हटा सकता है। इसके आस-पास जाने के लिए, अपने स्वयं के "ऑब्जेक्ट" प्रबंधक और संबंधित क्वेरीस उप-वर्ग प्रदान करें, जो नष्ट नहीं करता है - Django में ओवरराइडिंग QuerySet.delete () देखें


2
पुनश्च: और हाँ, जैसा कि अन्य उत्तर में है, जाने का तरीका शायद एक ReadOnlyAdmin वर्ग में उन तीन चीजों को परिभाषित करने के लिए है, और फिर उस से उप-वर्ग जहां भी आपको उस व्यवहार की आवश्यकता है। यहां तक ​​कि फैंसी भी प्राप्त कर सकते हैं और उन समूहों / अनुमतियों की परिभाषा को अनुमति दे सकते हैं जो संपादित करने की अनुमति देते हैं , और फिर ट्रू तदनुसार लौटते हैं (और get_readonly_fields () का उपयोग करें, जिनके पास अनुरोध तक पहुंच है और इसलिए वर्तमान उपयोगकर्ता है)।
डैनी डब्ल्यू। अडेयर

लगभग आदर्श। क्या मैं लालच से पूछ सकता हूं कि क्या पंक्तियों को एक संपादन पृष्ठ से लिंक नहीं करना है? (फिर, किसी भी पंक्ति में ज़ूम करने की आवश्यकता नहीं है, और किसी भी चीज़ को संपादित करने की आवश्यकता नहीं है)
स्टीव बेनेट

1
यदि आप अपने ModelAdmin की list_display_links को किसी ऐसी चीज़ पर सेट करते हैं, जो गलत (जैसे एक रिक्त सूची / टुपल) के रूप में मूल्यांकन करती है, तो ModelAdmin .__ init __ () सभी स्तंभों के लिए list_display_links सेट करता है (एक्शन चेकबॉक्स को छोड़कर) - विकल्प देखें। मुझे लगता है कि यह सुनिश्चित करने के लिए किया गया है कि लिंक हैं। इसलिए मैं एक रीडऑनलीमिन में __init __ () को ओवरराइड करूंगा, माता-पिता को कॉल करूंगा, फिर list_display_links को एक खाली सूची या ट्यूपल पर सेट कर दूंगा। यह देखते हुए कि अब आपके पास आसानी से परिवर्तित होने वाले फ़ॉर्म के लिंक नहीं होंगे, संभवतः इसके लिए एक पैरामीटर / क्लास विशेषता बनाने के लिए सबसे अच्छा है - मुझे नहीं लगेगा कि आम तौर पर वांछित व्यवहार होना चाहिए। Hth
डैनी डब्ल्यू। Adair

मॉडल से सेट किए जा रहे readonly_fields के बारे में, यह संभवत: काम नहीं करेगा यदि आप फॉर्म को ओवरराइड करते हैं और अन्य फ़ील्ड जोड़ते हैं ... वास्तविक फॉर्म फ़ील्ड पर आधारित यह संभवतः बेहतर है।
डैनी डब्ल्यू। Adair

यह काम नहीं किया: __init __ (सेल्फ, * आर्ग्स) को हराया: सुपर (RegistrationStatusAdmin, स्व) ।__ init __ (* आर्ग्स) self.display_links = []
स्टीव बेनेन

50

यहां दो कक्षाएं हैं जिनका मैं एक मॉडल बनाने के लिए उपयोग कर रहा हूं और / या यह केवल पढ़ने के लिए इनलाइन है।

मॉडल व्यवस्थापक के लिए:

from django.contrib import admin

class ReadOnlyAdmin(admin.ModelAdmin):
    readonly_fields = []

    def get_readonly_fields(self, request, obj=None):
        return list(self.readonly_fields) + \
               [field.name for field in obj._meta.fields] + \
               [field.name for field in obj._meta.many_to_many]


    def has_add_permission(self, request):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

class MyModelAdmin(ReadOnlyAdmin):
    pass

इनलाइन के लिए:

class ReadOnlyTabularInline(admin.TabularInline):
    extra = 0
    can_delete = False
    editable_fields = []
    readonly_fields = []
    exclude = []

    def get_readonly_fields(self, request, obj=None):
        return list(self.readonly_fields) + \
               [field.name for field in self.model._meta.fields
                if field.name not in self.editable_fields and
                   field.name not in self.exclude]

    def has_add_permission(self, request):
        return False


class MyInline(ReadOnlyTabularInline):
    pass

आप दोनों वर्गों को एक उप वर्ग में कैसे लागू करते हैं। उदाहरण के लिए, यदि मेरे पास सामान्य क्षेत्र हैं और एक कक्षा में सुर्खियों में हैं? क्या मैं दोनों का विस्तार कर सकता हूं?
तिमो

@timo इन वर्गों का मिश्रण के रूप में
मार्टिन 13

1
has_add_permissionमें ReadOnlyAdminएक पैरामीटर के रूप केवल अनुरोध लेता है
MartinM

has_change_permission () को भी ओवरराइड करने की आवश्यकता है। def has_change_permission (सेल्फ, रिक्वेस्ट, obj = कोई नहीं):
david euler

13

यदि आप चाहते हैं कि उपयोगकर्ता इस बात से अवगत हो कि वह इसे संपादित नहीं कर सकता है, तो पहले समाधान पर 2 टुकड़े गायब हैं। आपने डिलीट एक्शन हटा दिया है!

class MyAdmin(ModelAdmin)
    def has_add_permission(self, request, obj=None):
        return False
    def has_delete_permission(self, request, obj=None):
        return False

    def get_actions(self, request):
        actions = super(MyAdmin, self).get_actions(request)
        if 'delete_selected' in actions:
            del actions['delete_selected']
        return actions

दूसरा: सादे मॉडल पर पठनीय समाधान ठीक काम करता है। लेकिन यह काम नहीं करता है अगर आपके पास विदेशी कुंजी के साथ विरासत में मिला मॉडल है। दुर्भाग्य से, मैं अभी तक उस के लिए समाधान नहीं जानता। एक अच्छा प्रयास है:

पूरा मॉडल केवल पढ़ने के लिए

लेकिन यह मेरे लिए भी काम नहीं करता है।

और एक अंतिम नोट, यदि आप एक व्यापक समाधान पर सोचना चाहते हैं, तो आपको यह लागू करना होगा कि प्रत्येक इनलाइन को भी आसानी से पढ़ा जाना चाहिए।


11

वास्तव में आप इस सरल समाधान की कोशिश कर सकते हैं:

class ReadOnlyModelAdmin(admin.ModelAdmin):
    actions = None
    list_display_links = None
    # more stuff here

    def has_add_permission(self, request):
        return False
  • actions = None: "हटाए गए ..." विकल्प के साथ ड्रॉपडाउन दिखाने से बचा जाता है
  • list_display_links = None: उस वस्तु को संपादित करने के लिए कॉलम में क्लिक करने से बचा जाता है
  • has_add_permission() लौटकर झूठी उस मॉडल के लिए नई वस्तुओं को बनाने से बचा जाता है

1
यह खेतों को देखने के लिए किसी भी उदाहरण को खोलने से मना करता है, हालांकि अगर किसी को सिर्फ लिस्टिंग के साथ ठीक है, तो यह काम करता है।
सेबेस्टियन वनस्टीनिस्टिस्ट

8

यह Django 2.1 में जोड़ा गया था जो 8/1/18 को जारी किया गया था!

ModelAdmin.has_view_permission()बस मौजूदा has_delete_permission, has_change_permission और has_add_permission की तरह है। आप यहां डॉक्स में इसके बारे में पढ़ सकते हैं

जारी नोटों से:

यह उपयोगकर्ताओं को व्यवस्थापक में केवल पढ़ने के लिए मॉडल की अनुमति देता है। ModelAdmin.has_view_permission () नया है। कार्यान्वयन पीछे की ओर संगत है कि वस्तुओं को संपादित करने के लिए "परिवर्तन" अनुमति देने वाले उपयोगकर्ताओं को अनुमति देने के लिए "दृश्य" अनुमति देने की आवश्यकता नहीं है।


सुपरसुसर अभी भी व्यवस्थापक इंटरफ़ेस में ऑब्जेक्ट्स को संशोधित करने में सक्षम होगा, हालांकि, सही?
फ्लिम

यह सही है, जब तक कि आप सुपरसर्स की पहुंच को अस्वीकार करने के लिए व्यवहार को बदलने के लिए इन तरीकों में से एक को ओवरराइड नहीं करते हैं।
grrrrrr

6

यदि स्वीकृत उत्तर आपके लिए काम नहीं करता है, तो यह कोशिश करें:

def get_readonly_fields(self, request, obj=None):
    readonly_fields = []
    for field in self.model._meta.fields:
        readonly_fields.append(field.name)

    return readonly_fields

5

@Darklow और @josir के उत्कृष्ट उत्तरों को संकलित करना, इसके अलावा "सहेजें" और "सहेजें और जारी रखें" बटन को हटाने के लिए थोड़ा और जोड़ना (पायथन 3 सिंटैक्स में) होता है:

class ReadOnlyAdmin(admin.ModelAdmin):
    """Provides a read-only view of a model in Django admin."""
    readonly_fields = []

    def change_view(self, request, object_id, extra_context=None):
        """ customize add/edit form to remove save / save and continue """
        extra_context = extra_context or {}
        extra_context['show_save_and_continue'] = False
        extra_context['show_save'] = False
        return super().change_view(request, object_id, extra_context=extra_context)

    def get_actions(self, request):
        actions = super().get_actions(request)
        if 'delete_selected' in actions:
            del actions['delete_selected']
        return actions

    def get_readonly_fields(self, request, obj=None):
        return list(self.readonly_fields) + \
           [field.name for field in obj._meta.fields] + \
           [field.name for field in obj._meta.many_to_many]

    def has_add_permission(self, request):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

और फिर आप का उपयोग करें

class MyModelAdmin(ReadOnlyAdmin):
    pass

मैंने केवल Django 1.11 / पायथन 3 के साथ यह कोशिश की है।


जब से मैंने Django का उपयोग किया है, यह बहुत लंबा समय है। क्या कोई और इसके लिए व्रत कर सकता है?
स्टीव बेनेट

@SteveBennett ㄹ आवश्यकताओं पर बहुत सारी विविधताएँ हैं जो इस पते पर हैं ... यह उत्तर पानी-तंग नहीं है ... यहाँ स्पष्टीकरण का सुझाव दें: stackoverflow.com/a/36019597/2586761 और जवाब आपने stackoverflow.com पर टिप्पणी की। / a / 33543817/2586761 स्वीकृत उत्तर की तुलना में अधिक पूर्ण
ptim

3

स्वीकृत उत्तर को काम करना चाहिए, लेकिन यह पठनीय क्षेत्रों के प्रदर्शन क्रम को भी बनाए रखेगा। आपको इस समाधान के साथ मॉडल को हार्डकोड करने की भी आवश्यकता नहीं है।

class ReadonlyAdmin(admin.ModelAdmin):
   def __init__(self, model, admin_site):
      super(ReadonlyAdmin, self).__init__(model, admin_site)
      self.readonly_fields = [field.name for field in filter(lambda f: not f.auto_created, model._meta.fields)]

   def has_delete_permission(self, request, obj=None):
       return False
   def has_add_permission(self, request, obj=None):
       return False

3

Django 2.2 के साथ मैं इसे इस तरह करता हूं:

@admin.register(MyModel)
class MyAdmin(admin.ModelAdmin):
    readonly_fields = ('all', 'the', 'necessary', 'fields')
    actions = None # Removes the default delete action in list view

    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

django 2.2 के साथ, readonly_fieldsऔर actionsलाइनें आवश्यक नहीं हैं
cheng10

3

2.2 के साथ django, सरल रूप से व्यवस्थापक के रूप में सरल हो सकता है:

class ReadOnlyAdminMixin():
    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False


class LogEntryAdmin(ReadOnlyAdminMixin, admin.ModelAdmin):
    list_display = ('id', 'user', 'action_flag', 'content_type', 'object_repr')

1

मैं उसी आवश्यकता में भाग गया जब django व्यवस्थापक में कुछ उपयोगकर्ताओं के लिए सभी क्षेत्रों को आसानी से बनाने की आवश्यकता थी, django मॉड्यूल "django-admin-view-permission" पर अपने कोड को रोल किए बिना लीवरेजिंग समाप्त कर दी। यदि आपको स्पष्ट रूप से परिभाषित करने के लिए अधिक महीन दाने वाले नियंत्रण की आवश्यकता है कि कौन से क्षेत्र में हैं तो आपको मॉड्यूल का विस्तार करने की आवश्यकता होगी। आप यहां कार्रवाई में प्लगइन की जांच कर सकते हैं


0

read-only => अनुमति देखना

  1. pipenv install django-admin-view-permission
  2. सेटिंग में INSTALLED_APPS में add admin_view_permission ’जोड़ें। इसे भी इस तरह लिखें: ʻINSTALLED_APPS = ['admin_view_permission'
  3. python manage.py माइग्रेट करें
  4. अजगर प्रबंधन Oracle चलानेवाला 6666

ok.have 'विचारों' की अनुमति के साथ मज़ेदार


0

मैंने इनलाइन सहित, उपयोगकर्ता की अनुमति के आधार पर ReadOnly दृश्य को संभालने के लिए एक सामान्य वर्ग लिखा है;)

Model.py में:

class User(AbstractUser):
    ...
    def is_readonly(self):
        if self.is_superuser:
            return False
        # make readonly all users not in "admins" group
        adminGroup = Group.objects.filter(name="admins")
        if adminGroup in self.groups.all():
            return False
        return True

Admin.py में:

# read-only user filter class for ModelAdmin
class ReadOnlyAdmin(admin.ModelAdmin):
    def __init__(self, *args, **kwargs):
        # keep initial readonly_fields defined in subclass
        self._init_readonly_fields = self.readonly_fields
        # keep also inline readonly_fields
        for inline in self.inlines:
            inline._init_readonly_fields = inline.readonly_fields
        super().__init__(*args,**kwargs)
    # customize change_view to disable edition to readonly_users
    def change_view( self, request, object_id, form_url='', extra_context=None ):
        context = extra_context or {}
        # find whether it is readonly or not 
        if request.user.is_readonly():
            # put all fields in readonly_field list
            self.readonly_fields = [ field.name for field in self.model._meta.get_fields() if not field.auto_created ]
            # readonly mode fer all inlines
            for inline in self.inlines:
                inline.readonly_fields = [field.name for field in inline.model._meta.get_fields() if not field.auto_created]
            # remove edition buttons
            self.save_on_top = False
            context['show_save'] = False
            context['show_save_and_continue'] = False
        else:
            # if not readonly user, reset initial readonly_fields
            self.readonly_fields = self._init_readonly_fields
            # same for inlines
            for inline in self.inlines:
                inline.readonly_fields = self._init_readonly_fields
        return super().change_view(
                    request, object_id, form_url, context )
    def save_model(self, request, obj, form, change):
        # disable saving model for readonly users
        # just in case we have a malicious user...
        if request.user.is_readonly():
            # si és usuari readonly no guardem canvis
            return False
        # if not readonly user, save model
        return super().save_model( request, obj, form, change )

उसके बाद, हम सामान्य रूप से admin.py में अपनी कक्षाएं आमतौर पर ले सकते हैं:

class ContactAdmin(ReadOnlyAdmin):
    list_display = ("name","email","whatever")
    readonly_fields = ("updated","created")
    inlines = ( PhoneInline, ... )
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.