แอดมิน Django ซ่อนนางแบบ


87

ที่หน้ารูทของไซต์ผู้ดูแลระบบที่มีโมเดลที่ลงทะเบียนปรากฏขึ้นฉันต้องการซ่อนโมเดลต่างๆที่ลงทะเบียนกับผู้ดูแลระบบ Django

ถ้าฉันยกเลิกการลงทะเบียนโดยตรงฉันจะไม่สามารถเพิ่มระเบียนใหม่ได้เนื่องจากการเพิ่มสัญลักษณ์ใหม่ "+" หายไป

จะทำได้อย่างไร?

คำตอบ:


124

จากคำตอบของ x0nixฉันทำการทดลองบางอย่าง ดูเหมือนว่าจะส่งคืนคำสั่งที่ว่างเปล่าจากการget_model_permsไม่รวมโมเดลจาก index.html ในขณะที่ยังคงให้คุณแก้ไขอินสแตนซ์ได้โดยตรง

class MyModelAdmin(admin.ModelAdmin):
    def get_model_perms(self, request):
        """
        Return empty perms dict thus hiding the model from admin index.
        """
        return {}

admin.site.register(MyModel, MyModelAdmin)

ตกลง เท่านั้นที่เป็นปัญหาเมื่อฉันไม่ต้องการเปลี่ยนรหัส สิ่งที่ฉันหมายถึงคือฉันมีแอพพื้นฐานที่ฉันต้องการรักษาความสะอาดจากการพึ่งพาแอพอื่น ๆ ฉันเก็บการอ้างอิงเหล่านี้ไว้ในแอปเฉพาะโครงการที่ได้รับมา ตอนนี้ฉันต้องการให้อินเทอร์เฟซผู้ดูแลระบบแสดงเฉพาะแอปที่ได้รับไม่ใช่แอปพื้นฐาน Django ต้องการให้แอปพื้นฐานแสดงรายการในการตั้งค่า / INSTALLED_APPS เพื่อให้แอปที่ได้รับมาทำงาน เห็นได้ชัดว่าแอปพื้นฐานไม่ควรแสดง แต่ในขณะเดียวกันฉันก็ไม่ต้องการเก็บไว้โดยไม่มีการแก้ไขและนำกลับมาใช้ใหม่ดู [ที่นี่] ( Stack Exchange / questions / 13923968 /)
สเวน

6
วิธีที่สั้นกว่า:get_model_perms = lambda self, req: {}
Tigran Saluev

3
จะเกิดอะไรขึ้นถ้าฉันต้องการซ่อนโมเดลจาก userAdmin บางคน?
Alireza Sanaee

1
โปรดใช้ความระมัดระวังในการแก้ปัญหานี้แม้ว่าลิงก์จะหายไป แต่ผู้ใช้สามารถข้ามไปยังวัตถุได้เองดังนี้ / admin / main / comment / 2333 / change /
goodgrief

35

สำหรับ Django 1.8 ขึ้นไป

ตั้งแต่ Django 1.8 ModelAdminได้มีวิธีการใหม่ที่เรียกว่าhas_module_permission()ซึ่งมีหน้าที่ในการแสดงโมเดลในดัชนีผู้ดูแลระบบ

หากต้องการซ่อนรุ่นจากดัชนีผู้ดูแลระบบเพียงแค่สร้างวิธีการนี้ของคุณในการเรียนและผลตอบแทนModelAdmin Falseตัวอย่าง:

class MyModelAdmin(admin.ModelAdmin):
    ...
    def has_module_permission(self, request):
        return False

น่าเสียดายที่has_module_permissionส่งผลกระทบต่อแอปทั้งหมดไม่ใช่แค่รุ่นเดียว ดังนั้นการเพิ่มสิ่งนี้ลงในโมเดลในแอพทำให้เกิด 403 Forbidden ในรายการโมเดลแอพ (/ admin / app_label /) ดูDjango / contrib / ธุรการ / sites.py
Fabian

1
@ ฟาเบียนคิดว่าเป็นบั๊ก ฉันถามสิ่งนี้ในช่อง IRC ของ Django และบางคนก็ยอมรับว่าพฤติกรรมนี้ไม่เป็นที่ต้องการ
xyres

@Fabian สมมติหน้าดัชนีผู้ดูแลระบบยังคงเชื่อมโยงไปยัง/ ธุรการ /return request.path!='/admin/'มันเป็นไปได้ที่จะหลีกเลี่ยงข้อผิดพลาดที่โดยสิ่งที่ต้องการ น่าเสียดายที่เปิดใช้งานโมเดลเหล่านั้นอีกครั้งในรายการรุ่นของแอพ
ecp

ฉันได้เปิดตั๋วที่นี่สำหรับข้อบกพร่องนี้ นี้ได้รับการแก้ไขที่นี่ มันควรจะรวมอยู่ในรุ่นถัดไปหวังว่า
xyres

ใน Django 1.11 ลิงก์ในรายละเอียดยังคงใช้งานได้ แต่เอนทิตีไม่อยู่ในหน้าจอผู้ดูแลระบบหลัก
Csaba Toth

22

มีปัญหาเดียวกันนี่คือสิ่งที่ฉันคิด

เช่นเดียวกับในโซลูชันก่อนหน้า - คัดลอก index.html จาก django ไปยัง /admin/index.html ของคุณและแก้ไขดังนี้:

{% for model in app.models %}
    {% if not model.perms.list_hide %}
    <tr>
    ...
    </tr>
    {% endif %}
{% endfor %}

และสร้างคลาสย่อย ModelAdmin:

class HiddenModelAdmin(admin.ModelAdmin):
    def get_model_perms(self, *args, **kwargs):
        perms = admin.ModelAdmin.get_model_perms(self, *args, **kwargs)
        perms['list_hide'] = True
        return perms

ตอนนี้โมเดลใด ๆ ที่ลงทะเบียนกับคลาสย่อย HiddenModelAdmin จะไม่ปรากฏในรายการผู้ดูแลระบบ แต่จะพร้อมใช้งานผ่านสัญลักษณ์ "บวก" โดยละเอียด:

class MyModelAdmin(HiddenModelAdmin):
    ...

admin.site.register(MyModel, MyModelAdmin)

1

วิธีแก้ที่น่าเกลียด: แทนที่เทมเพลตดัชนีผู้ดูแลระบบเช่นคัดลอก index.html จาก django ไปยัง /admin/index.html ของคุณและเพิ่มสิ่งนี้:

{% for for model in app.models %}
    {% ifnotequal model.name "NameOfModelToHide" %}
    ...

1

นี่คือสิ่งปลูกสร้างทางเลือกที่อยู่ในคำตอบด้านบนของ x0nix และเฉพาะในกรณีที่คุณพอใจที่จะซ่อนแถวด้วย jquery

คัดลอกการวางจากคำตอบอื่นในส่วนที่ฉันใช้ซ้ำ

class HiddenModelAdmin(admin.ModelAdmin):
def get_model_perms(self, *args, **kwargs):
    perms = admin.ModelAdmin.get_model_perms(self, *args, **kwargs)
    perms['list_hide'] = True
    return perms

class MyModelAdmin(HiddenModelAdmin):
...

admin.site.register(MyModel, MyModelAdmin)

จากนั้นติดตั้งdjango-jqueryจากนั้นเพิ่มบล็อกต่อไปนี้ใน/admin/index.htmlเทมเพลตของคุณ:

{% extends "admin:admin/index.html" %}

{% block extrahead %}
    <script type="text/javascript" src="{{ STATIC_URL }}js/jquery.js"></script>
    {% if app_list %}
      <script type="text/javascript">
        $(function(){
          {% for app in app_list %}
            {% for model in app.models %}
                {% if model.perms.list_hide %}
                    $('div.app-{{ app.app_label }}').find('tr.model-{{ model.object_name|lower }}').hide();
                {% endif %}
            {% endfor %}
          {% endfor %}
        });
     </script>
   {% endif %}
{% endblock %}

คุณไม่จำเป็นต้องคัดลอกและวางแม่แบบทั้งหมดเพียงแค่ขยายและลบล้างextraheadบล็อก คุณจะต้องใช้django-apptemplatesสำหรับข้างต้นจึงจะทำงานได้


0

Django 1.2 มีคำสั่ง if ใหม่ซึ่งหมายความว่าสามารถรับคุณลักษณะที่ต้องการได้โดยการเขียนทับ admin / index.html เท่านั้น

{% if model.name not in "Name of hidden model; Name of other hidden model" %}
    ...
{% endif %}

นี่เป็นวิธีแก้ปัญหาที่ไม่ดีเนื่องจากไม่สนใจผู้ดูแลระบบที่มีหลายภาษา แน่นอนคุณสามารถเพิ่มชื่อรุ่นในภาษาที่รองรับทั้งหมด เป็นทางออกที่ดีเพราะไม่ได้เขียนทับฟังก์ชันหลักของ Django มากกว่าหนึ่งด้าน

แต่ก่อนจะเปลี่ยนอะไรคิดว่าคนเราน่าจะคิดถึงเรื่องนี้ ...

โดยพื้นฐานแล้วปัญหาเกี่ยวข้องกับการมีโมเดลที่ไม่ต้องการใช้มากกว่าการเพิ่มตัวเลือกในเมนูแบบเลื่อนลงเป็นครั้งคราว สามารถแก้ไขได้อย่างมีประสิทธิภาพโดยการสร้างชุดสิทธิ์สำหรับผู้ใช้ "ไม่ขั้นสูง" ที่ตื่นตระหนกเมื่อมีโมเดลมากเกินไป ในกรณีที่จำเป็นต้องมีการเปลี่ยนแปลงในบางรุ่นคุณสามารถเข้าสู่ระบบด้วย "บัญชีขั้นสูง"


0

ฉันมีผู้ดูแลโมเดลจำนวนมากที่จะลงทะเบียนและซ่อนหากคุณต้องการโซลูชันที่แห้งกว่านี้ใช้ได้กับฉัน (Django 1.10, Python 3.5)

# admin.py

def register_hidden_models(*model_names):
    for m in model_names:
        ma = type(
            str(m)+'Admin',
            (admin.ModelAdmin,),
            {
                'get_model_perms': lambda self, request: {}
            })
        admin.site.register(m, ma)

register_hidden_models(MyModel1, MyModel2, MyModel3)

ฉันเดาว่าคุณสามารถเปลี่ยนเป็นคลาสยูทิลิตี้ได้หากคุณต้องการใช้ซ้ำในแอปต่างๆ


0

ในฐานะของ Django 1.8.18 , has_module_permission()ยังคงมีปัญหา ดังนั้นในกรณีของเราเราก็ใช้ไฟล์get_model_perms(). ในทำนองเดียวกันเราจำเป็นต้องซ่อนโมเดลสำหรับผู้ใช้บางรายเท่านั้น แต่superuserควรจะสามารถเข้าถึงรายการดัชนีได้

class MyModelAdmin(admin.ModelAdmin):
    def get_model_perms(self, request):
        if not request.user.is_superuser:
            return {}
        return super(MyModelAdmin, self).get_model_perms(request)

admin.site.register(MyModel, MyModelAdmin)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.