【问题标题】:Django admin different inlines for change and add viewDjango admin 不同的内联用于更改和添加视图
【发布时间】:2011-01-15 04:24:33
【问题描述】:

我需要单独的视图来添加和更改页面。在添加页面中,我想从内联表单集中排除一些字段。我准备了两个 TabularInline 类,其中一个包含属性“排除”。我尝试按如下方式使用它们:

class BoxAdmin(admin.ModelAdmin):
    def change_view(self, request, obj_id):
        self.inlines=[ItemChangeInline,]
        return super(BoxAdmin, self).change_view(self.request, obj_id)
    def add_view(self, request):
        self.inlines=[ItemAddInline,]
        return super(BoxAdmin, self).add_view(self, request)

没有效果(根本没有显示内联)。

【问题讨论】:

    标签: django django-admin django-forms inlines


    【解决方案1】:

    它适用于 Django 1.5+ 并且看起来很优雅:

    // admin.py
    class BoxAdmin(ModelAdmin):
    
        inlines = ()
    
        def change_view(self, request, object_id, form_url='', extra_context=None):
            self.inlines = (ItemChangeInline, )
            return super(BoxAdmin, self).change_view(request, object_id)
    
        def add_view(self, request, form_url='', extra_context=None):
            self.inlines = (ItemAddInline, )
            return super(BoxAdmin, self).add_view(request)
    

    希望对大家有用

    【讨论】:

    • 我逐字使用它并且它有效,但我用return super(BoxAdmin, self).change_view(request, object_id, form_url, extra_context)return super(BoxAdmin, self).add_view(request, form_url, extra_context)替换了两个返回
    【解决方案2】:

    这是似乎可以工作的代码:

    class BoxAdmin(admin.ModelAdmin):
       def change_view(self, request, obj_id):
            self.inlines=[ItemChangeInline,]
            for inline_class in self.inlines:
                inline_instance = inline_class(self.model, self.admin_site)
                self.inline_instances.append(inline_instance)
            return super(BoxAdmin, self).change_view(request, obj_id)
        def add_view(self, request):
            self.inlines=[ItemAddInline,]
            for inline_class in self.inlines:
                inline_instance = inline_class(self.model, self.admin_site)
                self.inline_instances.append(inline_instance)
            return super(BoxAdmin, self).add_view(request)
    

    但是,这看起来不优雅,因为这部分:

                for inline_class in self.inlines:
                inline_instance = inline_class(self.model, self.admin_site)
                self.inline_instances.append(inline_instance)
    

    是 admin.ModelAdmin 的 init 方法的复制粘贴(因此它运行两次)。

    【讨论】:

      【解决方案3】:

      为什么在 add_view 中有 .add_view(self, request) 而在更改视图中有 .change_view(self.request, ..)?我相信,您不需要在 add_view 中使用 self,因为您使用的是 super。

      【讨论】:

        【解决方案4】:

        我遇到了一种情况,我需要根据您为给定故事使用的管理站点显示内联。

        扩展 alekwisnia 的答案,我能够使用以下代码获得适用于 Django 1.3 的动态内联:

        在 highlight/admin.py 中

        class HighlightInline(generic.GenericTabularInline):
            model = Highlight
            extra = 1
            max_num = 4
            fields = ('order', 'highlight')
            template = 'admin/highlights/inline.html'
        
        class HighlightAdmin(admin.ModelAdmin):
            def regulate_highlight_inlines(self):
                highlights_enabled = Setting.objects.get_or_default('highlights_enabled', default='')
                highlight_inline_instance = HighlightInline(self.model, self.admin_site)
                highlight_found = any(isinstance(x, HighlightInline) for x in self.inline_instances)
                if highlights_enabled.strip().lower() == 'true':
                    if not highlight_found:
                        self.inline_instances.insert(0, highlight_inline_instance)
                else:
                    if highlight_found:
                        self.inline_instances.pop(0)
                print self.inline_instances
        
            def change_view(self, request, object_id, form_url='', extra_context=None):
                self.regulate_highlight_inlines()
                return super(HighlightAdmin, self).change_view(request, object_id)
        
            def add_view(self, request, form_url='', extra_context=None):
                self.regulate_highlight_inlines()   
                return super(HighlightAdmin, self).add_view(request, form_url, extra_context)
        

        在故事/admin.py中

        class StoryAdmin(HighlightAdmin):
        

        需要注意的一点是,我不仅仅是在操作内联类 (HighlightInline),而是在更改内联实例 (HighlightInline(self.model, self.admin_site))。这是因为 django 在 admin 类的初始构建过程中,已经根据内联类列表构建了内联实例列表。

        【讨论】:

          【解决方案5】:

          Django 1.3 的另一种解决方案

          class BoxAdmin(admin.ModelAdmin):
          
              def change_view(self, request, object_id, form_url='', extra_context=None):
                  self.inline_instances = [ItemChangeInline(self.model, self.admin_site)]
                  return super(BoxAdmin, self).change_view(request, object_id, extra_context)
          
              def add_view(self, request, form_url='', extra_context=None):
                  self.inline_instances = [ItemAddInline(self.model, self.admin_site)]
                  return super(BoxAdmin, self).add_view(request, form_url, extra_context)
          

          【讨论】:

            【解决方案6】:

            受到你们回答的启发, 我能够向 admin.site 添加更多自定义视图。

            很多时候,只是想要addchange 不同设置的页面,而不是真正的额外浏览量

            # admin.py
            class FooAdmin(admin.ModelAdmin):
                ....
                def edit_tag(self, obj):              # add a Link tag to change-list page
                    return mark_safe('<a href="{}?edit=True">Edit</a>'.format(obj.get_absolute_url()))
            
                edit_tag.short_description = u'Extra Action'
            
                def change_view(self, request, object_id, form_url='', extra_context=None):
                    if request.GET.get('edit', False):
                        self.readonly_fields = (
                            'total_amount',
                        )
                        self.inlines = []
                    else:
                        self.readonly_fields = (
                            'name', 'client', 'constructor', 'total_amount'
                        )
                        self.inlines = [TransactionInline]
                    return super(ProjectAdmin, self).change_view(request, object_id)
            
                def add_view(self, request, form_url='', extra_context=None):
                    self.readonly_fields = (
                        'total_amount',
                    )
                    self.inlines = []
                    return super(ProjectAdmin, self).add_view(request)
            

            在此之后,我将拥有三个视图:

            1. 添加视图 - 无需内联表单集,无需添加相关对象。

            2. 更改视图 1 - 使用内联表单集,仅用于添加内联数据(相关对象),对象的字段是只读的。

            3. 更改视图 2 - 没有内联表单集,仅用于更改对象。

            真的很简单,我们可以做得更多,谢谢大家。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-10-19
              • 1970-01-01
              • 2011-07-30
              • 1970-01-01
              • 2017-02-24
              • 2011-10-04
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多