Django admin different inlines for change and add view

前端 未结 6 576
醉酒成梦
醉酒成梦 2020-12-13 07:32

I need separate views for add and change page. In add page I\'d like to exclude some fields from inline formset. I\'ve prepared two TabularInline classes, one of them contai

相关标签:
6条回答
  • 2020-12-13 08:05

    Why in add_view you have .add_view(self, request) and in change view you have .change_view(self.request, ..)? I believe, you don't need self in add_view, since you use super.

    0 讨论(0)
  • 2020-12-13 08:09

    Inspired by you guys answer, I was able to add more custom views to the admin.site.

    Many times, just want add and change pages of different settings, not real extra views

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

    After this I'll have three views:

    1. add view - without inline formset, no need to add related objects.

    2. change view 1 - with inline formset, only for adding inline data(related objects), the the object's field is readonly.

    3. change view 2 - without inline formset, only for changing the object.

    Really simple, and we can do more, thanks everyone.

    0 讨论(0)
  • 2020-12-13 08:11

    It works with Django 1.5+ and seems fine & elegant:

    // 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)
    

    hope it can be useful for anyone

    0 讨论(0)
  • 2020-12-13 08:21

    Another solution to 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)
    
    0 讨论(0)
  • 2020-12-13 08:27

    I had a situation where I needed to show an Inline based on the admin site that you were on for a given story.

    Expanding on alekwisnia's answer, I was able to get dynamic inlines working for Django 1.3 using the following code:

    In highlights/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)
    

    In story/admin.py

    class StoryAdmin(HighlightAdmin):
    

    One thing to note is that I'm not merely manipulating inline classes(HighlightInline) but rather, I'm changing inline instances(HighlightInline(self.model, self.admin_site)). This is because django has already constructed a list of inline instances based on a list of inline classes during the initial construction of the admin class.

    0 讨论(0)
  • 2020-12-13 08:31

    Here is the code that seems to be working:

    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)
    

    However, this looks inelegant, cause this part:

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

    is a copy-paste from init method of admin.ModelAdmin (so it is run twice).

    0 讨论(0)
提交回复
热议问题