Show children inline in Django admin





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















In Django 1.11, I have 2 models, Foo and Bar:



class Foo(models.Model):
name = models.CharField()

class Bar(models.Model):
name = models.CharField()
foo = models.ForeignKey(Foo)


When I visit the Foo page in the Django admin, I want to be able to see a list of its Bars underneath it. So I do this in admin.py:



class BarInline(admin.StackedInline):
model = Bar

@admin.register(Foo)
class FooAdmin(admin.ModelAdmin):
list_display = ('name')
fields = ('name')
inlines = [BarInline]


But what I really want is a list of clickable links to a separate page where I can edit each Bar (as well as a Add button to add a new Bar to this Foo). I.e. I don't want the entire inline form. How is this possible in Django?










share|improve this question





























    1















    In Django 1.11, I have 2 models, Foo and Bar:



    class Foo(models.Model):
    name = models.CharField()

    class Bar(models.Model):
    name = models.CharField()
    foo = models.ForeignKey(Foo)


    When I visit the Foo page in the Django admin, I want to be able to see a list of its Bars underneath it. So I do this in admin.py:



    class BarInline(admin.StackedInline):
    model = Bar

    @admin.register(Foo)
    class FooAdmin(admin.ModelAdmin):
    list_display = ('name')
    fields = ('name')
    inlines = [BarInline]


    But what I really want is a list of clickable links to a separate page where I can edit each Bar (as well as a Add button to add a new Bar to this Foo). I.e. I don't want the entire inline form. How is this possible in Django?










    share|improve this question

























      1












      1








      1


      2






      In Django 1.11, I have 2 models, Foo and Bar:



      class Foo(models.Model):
      name = models.CharField()

      class Bar(models.Model):
      name = models.CharField()
      foo = models.ForeignKey(Foo)


      When I visit the Foo page in the Django admin, I want to be able to see a list of its Bars underneath it. So I do this in admin.py:



      class BarInline(admin.StackedInline):
      model = Bar

      @admin.register(Foo)
      class FooAdmin(admin.ModelAdmin):
      list_display = ('name')
      fields = ('name')
      inlines = [BarInline]


      But what I really want is a list of clickable links to a separate page where I can edit each Bar (as well as a Add button to add a new Bar to this Foo). I.e. I don't want the entire inline form. How is this possible in Django?










      share|improve this question














      In Django 1.11, I have 2 models, Foo and Bar:



      class Foo(models.Model):
      name = models.CharField()

      class Bar(models.Model):
      name = models.CharField()
      foo = models.ForeignKey(Foo)


      When I visit the Foo page in the Django admin, I want to be able to see a list of its Bars underneath it. So I do this in admin.py:



      class BarInline(admin.StackedInline):
      model = Bar

      @admin.register(Foo)
      class FooAdmin(admin.ModelAdmin):
      list_display = ('name')
      fields = ('name')
      inlines = [BarInline]


      But what I really want is a list of clickable links to a separate page where I can edit each Bar (as well as a Add button to add a new Bar to this Foo). I.e. I don't want the entire inline form. How is this possible in Django?







      python django






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 3 at 15:54









      GluePearGluePear

      2,98063263




      2,98063263
























          2 Answers
          2






          active

          oldest

          votes


















          1














          admin.py

          from django.urls import reverse
          from django.utils.html import format_html_join

          @admin.register(Foo)
          class FooAdmin(admin.ModelAdmin):
          list_display = ('name')
          fields = ('name', get_related, )
          readonly_fields = (get_related, )

          def get_related(self, instance):
          obj = instance.bar_set.all()
          return format_html_join(
          ',',
          '<a href="{}">{}</a>',
          ((
          reverse('admin:{{ app_label }}_bar_change', args=(c.id,)),
          c.name
          ) for c in obj),
          )


          You can create a callable readonly field which will return the reversed admin url of each relation wrapped in the relevant html code.



          This will result in something like:




          "your readonly field": link1, link2, link3







          share|improve this answer


























          • Thanks for the detailed response. Unfortunately this is not outputting any HTML.

            – GluePear
            Jan 4 at 9:04













          • @GluePear Reverse relations are called with <model_name>_set unless you set a related_name. On error, this callable will fail silently, I think. Try: >>> p = Foo.objects.first() and then >>>dir(p) to see how you can call the related Bar. Otherwise, install ipdb and try to set import pdb; pdb.set_trace() # XXX BREAKPOINT before return to get a debugging prompt.

            – raratiru
            Jan 4 at 9:16













          • @GluePear There is also a gotcha in the admin:yourapp_bar_change. yourapp is the name of the application your model Bar lies in. yourproject/yourapp/models.py. You can also find it in the admin url when you change an instance of the model Bar: Something like http://127.0.0.1/admin/yourapp/bar/1/change/. I changed yourapp to {{ app_label }} as in the docs.

            – raratiru
            Jan 4 at 9:28











          • Thanks for persevering. My problem was that I also needed to specify get_related in my fields variable (as well as in readonly_fields).

            – GluePear
            Jan 4 at 9:52











          • @GluePear Oh, indeed, I blindly copy-pasted the code, in my implementation I had fileds='__all__'.

            – raratiru
            Jan 4 at 10:17





















          1














          You can make all the fields readonly in BarInline.



          class BarInline(admin.StackedInline):
          model = Bar
          readonly_fields = ('id', 'name', 'foo')
          extra = 0


          And for the Add functionality you can modify the inline template or more easy probably, add a custom field in FooAdmin, something like:



          class FooAdmin(admin.ModelAdmin):
          list_display = ('name')
          fields = ('name', 'custom_add_bar')
          inlines = [BarInline]

          def custom_add_bar(self, obj):
          add_url = reverse('admin:appname_bar_add')
          return mark_safe(f'<a href="{add_url}">Add Bar</a>')


          Documentation for reversing admin urls






          share|improve this answer
























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54025679%2fshow-children-inline-in-django-admin%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            admin.py

            from django.urls import reverse
            from django.utils.html import format_html_join

            @admin.register(Foo)
            class FooAdmin(admin.ModelAdmin):
            list_display = ('name')
            fields = ('name', get_related, )
            readonly_fields = (get_related, )

            def get_related(self, instance):
            obj = instance.bar_set.all()
            return format_html_join(
            ',',
            '<a href="{}">{}</a>',
            ((
            reverse('admin:{{ app_label }}_bar_change', args=(c.id,)),
            c.name
            ) for c in obj),
            )


            You can create a callable readonly field which will return the reversed admin url of each relation wrapped in the relevant html code.



            This will result in something like:




            "your readonly field": link1, link2, link3







            share|improve this answer


























            • Thanks for the detailed response. Unfortunately this is not outputting any HTML.

              – GluePear
              Jan 4 at 9:04













            • @GluePear Reverse relations are called with <model_name>_set unless you set a related_name. On error, this callable will fail silently, I think. Try: >>> p = Foo.objects.first() and then >>>dir(p) to see how you can call the related Bar. Otherwise, install ipdb and try to set import pdb; pdb.set_trace() # XXX BREAKPOINT before return to get a debugging prompt.

              – raratiru
              Jan 4 at 9:16













            • @GluePear There is also a gotcha in the admin:yourapp_bar_change. yourapp is the name of the application your model Bar lies in. yourproject/yourapp/models.py. You can also find it in the admin url when you change an instance of the model Bar: Something like http://127.0.0.1/admin/yourapp/bar/1/change/. I changed yourapp to {{ app_label }} as in the docs.

              – raratiru
              Jan 4 at 9:28











            • Thanks for persevering. My problem was that I also needed to specify get_related in my fields variable (as well as in readonly_fields).

              – GluePear
              Jan 4 at 9:52











            • @GluePear Oh, indeed, I blindly copy-pasted the code, in my implementation I had fileds='__all__'.

              – raratiru
              Jan 4 at 10:17


















            1














            admin.py

            from django.urls import reverse
            from django.utils.html import format_html_join

            @admin.register(Foo)
            class FooAdmin(admin.ModelAdmin):
            list_display = ('name')
            fields = ('name', get_related, )
            readonly_fields = (get_related, )

            def get_related(self, instance):
            obj = instance.bar_set.all()
            return format_html_join(
            ',',
            '<a href="{}">{}</a>',
            ((
            reverse('admin:{{ app_label }}_bar_change', args=(c.id,)),
            c.name
            ) for c in obj),
            )


            You can create a callable readonly field which will return the reversed admin url of each relation wrapped in the relevant html code.



            This will result in something like:




            "your readonly field": link1, link2, link3







            share|improve this answer


























            • Thanks for the detailed response. Unfortunately this is not outputting any HTML.

              – GluePear
              Jan 4 at 9:04













            • @GluePear Reverse relations are called with <model_name>_set unless you set a related_name. On error, this callable will fail silently, I think. Try: >>> p = Foo.objects.first() and then >>>dir(p) to see how you can call the related Bar. Otherwise, install ipdb and try to set import pdb; pdb.set_trace() # XXX BREAKPOINT before return to get a debugging prompt.

              – raratiru
              Jan 4 at 9:16













            • @GluePear There is also a gotcha in the admin:yourapp_bar_change. yourapp is the name of the application your model Bar lies in. yourproject/yourapp/models.py. You can also find it in the admin url when you change an instance of the model Bar: Something like http://127.0.0.1/admin/yourapp/bar/1/change/. I changed yourapp to {{ app_label }} as in the docs.

              – raratiru
              Jan 4 at 9:28











            • Thanks for persevering. My problem was that I also needed to specify get_related in my fields variable (as well as in readonly_fields).

              – GluePear
              Jan 4 at 9:52











            • @GluePear Oh, indeed, I blindly copy-pasted the code, in my implementation I had fileds='__all__'.

              – raratiru
              Jan 4 at 10:17
















            1












            1








            1







            admin.py

            from django.urls import reverse
            from django.utils.html import format_html_join

            @admin.register(Foo)
            class FooAdmin(admin.ModelAdmin):
            list_display = ('name')
            fields = ('name', get_related, )
            readonly_fields = (get_related, )

            def get_related(self, instance):
            obj = instance.bar_set.all()
            return format_html_join(
            ',',
            '<a href="{}">{}</a>',
            ((
            reverse('admin:{{ app_label }}_bar_change', args=(c.id,)),
            c.name
            ) for c in obj),
            )


            You can create a callable readonly field which will return the reversed admin url of each relation wrapped in the relevant html code.



            This will result in something like:




            "your readonly field": link1, link2, link3







            share|improve this answer















            admin.py

            from django.urls import reverse
            from django.utils.html import format_html_join

            @admin.register(Foo)
            class FooAdmin(admin.ModelAdmin):
            list_display = ('name')
            fields = ('name', get_related, )
            readonly_fields = (get_related, )

            def get_related(self, instance):
            obj = instance.bar_set.all()
            return format_html_join(
            ',',
            '<a href="{}">{}</a>',
            ((
            reverse('admin:{{ app_label }}_bar_change', args=(c.id,)),
            c.name
            ) for c in obj),
            )


            You can create a callable readonly field which will return the reversed admin url of each relation wrapped in the relevant html code.



            This will result in something like:




            "your readonly field": link1, link2, link3








            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 4 at 9:52









            GluePear

            2,98063263




            2,98063263










            answered Jan 3 at 17:50









            raratiruraratiru

            3,18522359




            3,18522359













            • Thanks for the detailed response. Unfortunately this is not outputting any HTML.

              – GluePear
              Jan 4 at 9:04













            • @GluePear Reverse relations are called with <model_name>_set unless you set a related_name. On error, this callable will fail silently, I think. Try: >>> p = Foo.objects.first() and then >>>dir(p) to see how you can call the related Bar. Otherwise, install ipdb and try to set import pdb; pdb.set_trace() # XXX BREAKPOINT before return to get a debugging prompt.

              – raratiru
              Jan 4 at 9:16













            • @GluePear There is also a gotcha in the admin:yourapp_bar_change. yourapp is the name of the application your model Bar lies in. yourproject/yourapp/models.py. You can also find it in the admin url when you change an instance of the model Bar: Something like http://127.0.0.1/admin/yourapp/bar/1/change/. I changed yourapp to {{ app_label }} as in the docs.

              – raratiru
              Jan 4 at 9:28











            • Thanks for persevering. My problem was that I also needed to specify get_related in my fields variable (as well as in readonly_fields).

              – GluePear
              Jan 4 at 9:52











            • @GluePear Oh, indeed, I blindly copy-pasted the code, in my implementation I had fileds='__all__'.

              – raratiru
              Jan 4 at 10:17





















            • Thanks for the detailed response. Unfortunately this is not outputting any HTML.

              – GluePear
              Jan 4 at 9:04













            • @GluePear Reverse relations are called with <model_name>_set unless you set a related_name. On error, this callable will fail silently, I think. Try: >>> p = Foo.objects.first() and then >>>dir(p) to see how you can call the related Bar. Otherwise, install ipdb and try to set import pdb; pdb.set_trace() # XXX BREAKPOINT before return to get a debugging prompt.

              – raratiru
              Jan 4 at 9:16













            • @GluePear There is also a gotcha in the admin:yourapp_bar_change. yourapp is the name of the application your model Bar lies in. yourproject/yourapp/models.py. You can also find it in the admin url when you change an instance of the model Bar: Something like http://127.0.0.1/admin/yourapp/bar/1/change/. I changed yourapp to {{ app_label }} as in the docs.

              – raratiru
              Jan 4 at 9:28











            • Thanks for persevering. My problem was that I also needed to specify get_related in my fields variable (as well as in readonly_fields).

              – GluePear
              Jan 4 at 9:52











            • @GluePear Oh, indeed, I blindly copy-pasted the code, in my implementation I had fileds='__all__'.

              – raratiru
              Jan 4 at 10:17



















            Thanks for the detailed response. Unfortunately this is not outputting any HTML.

            – GluePear
            Jan 4 at 9:04







            Thanks for the detailed response. Unfortunately this is not outputting any HTML.

            – GluePear
            Jan 4 at 9:04















            @GluePear Reverse relations are called with <model_name>_set unless you set a related_name. On error, this callable will fail silently, I think. Try: >>> p = Foo.objects.first() and then >>>dir(p) to see how you can call the related Bar. Otherwise, install ipdb and try to set import pdb; pdb.set_trace() # XXX BREAKPOINT before return to get a debugging prompt.

            – raratiru
            Jan 4 at 9:16







            @GluePear Reverse relations are called with <model_name>_set unless you set a related_name. On error, this callable will fail silently, I think. Try: >>> p = Foo.objects.first() and then >>>dir(p) to see how you can call the related Bar. Otherwise, install ipdb and try to set import pdb; pdb.set_trace() # XXX BREAKPOINT before return to get a debugging prompt.

            – raratiru
            Jan 4 at 9:16















            @GluePear There is also a gotcha in the admin:yourapp_bar_change. yourapp is the name of the application your model Bar lies in. yourproject/yourapp/models.py. You can also find it in the admin url when you change an instance of the model Bar: Something like http://127.0.0.1/admin/yourapp/bar/1/change/. I changed yourapp to {{ app_label }} as in the docs.

            – raratiru
            Jan 4 at 9:28





            @GluePear There is also a gotcha in the admin:yourapp_bar_change. yourapp is the name of the application your model Bar lies in. yourproject/yourapp/models.py. You can also find it in the admin url when you change an instance of the model Bar: Something like http://127.0.0.1/admin/yourapp/bar/1/change/. I changed yourapp to {{ app_label }} as in the docs.

            – raratiru
            Jan 4 at 9:28













            Thanks for persevering. My problem was that I also needed to specify get_related in my fields variable (as well as in readonly_fields).

            – GluePear
            Jan 4 at 9:52





            Thanks for persevering. My problem was that I also needed to specify get_related in my fields variable (as well as in readonly_fields).

            – GluePear
            Jan 4 at 9:52













            @GluePear Oh, indeed, I blindly copy-pasted the code, in my implementation I had fileds='__all__'.

            – raratiru
            Jan 4 at 10:17







            @GluePear Oh, indeed, I blindly copy-pasted the code, in my implementation I had fileds='__all__'.

            – raratiru
            Jan 4 at 10:17















            1














            You can make all the fields readonly in BarInline.



            class BarInline(admin.StackedInline):
            model = Bar
            readonly_fields = ('id', 'name', 'foo')
            extra = 0


            And for the Add functionality you can modify the inline template or more easy probably, add a custom field in FooAdmin, something like:



            class FooAdmin(admin.ModelAdmin):
            list_display = ('name')
            fields = ('name', 'custom_add_bar')
            inlines = [BarInline]

            def custom_add_bar(self, obj):
            add_url = reverse('admin:appname_bar_add')
            return mark_safe(f'<a href="{add_url}">Add Bar</a>')


            Documentation for reversing admin urls






            share|improve this answer




























              1














              You can make all the fields readonly in BarInline.



              class BarInline(admin.StackedInline):
              model = Bar
              readonly_fields = ('id', 'name', 'foo')
              extra = 0


              And for the Add functionality you can modify the inline template or more easy probably, add a custom field in FooAdmin, something like:



              class FooAdmin(admin.ModelAdmin):
              list_display = ('name')
              fields = ('name', 'custom_add_bar')
              inlines = [BarInline]

              def custom_add_bar(self, obj):
              add_url = reverse('admin:appname_bar_add')
              return mark_safe(f'<a href="{add_url}">Add Bar</a>')


              Documentation for reversing admin urls






              share|improve this answer


























                1












                1








                1







                You can make all the fields readonly in BarInline.



                class BarInline(admin.StackedInline):
                model = Bar
                readonly_fields = ('id', 'name', 'foo')
                extra = 0


                And for the Add functionality you can modify the inline template or more easy probably, add a custom field in FooAdmin, something like:



                class FooAdmin(admin.ModelAdmin):
                list_display = ('name')
                fields = ('name', 'custom_add_bar')
                inlines = [BarInline]

                def custom_add_bar(self, obj):
                add_url = reverse('admin:appname_bar_add')
                return mark_safe(f'<a href="{add_url}">Add Bar</a>')


                Documentation for reversing admin urls






                share|improve this answer













                You can make all the fields readonly in BarInline.



                class BarInline(admin.StackedInline):
                model = Bar
                readonly_fields = ('id', 'name', 'foo')
                extra = 0


                And for the Add functionality you can modify the inline template or more easy probably, add a custom field in FooAdmin, something like:



                class FooAdmin(admin.ModelAdmin):
                list_display = ('name')
                fields = ('name', 'custom_add_bar')
                inlines = [BarInline]

                def custom_add_bar(self, obj):
                add_url = reverse('admin:appname_bar_add')
                return mark_safe(f'<a href="{add_url}">Add Bar</a>')


                Documentation for reversing admin urls







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 3 at 17:27









                grouchoboygrouchoboy

                49639




                49639






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54025679%2fshow-children-inline-in-django-admin%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    MongoDB - Not Authorized To Execute Command

                    How to fix TextFormField cause rebuild widget in Flutter

                    Npm cannot find a required file even through it is in the searched directory