Allow applications to register links in the admin interface

219 views
Skip to first unread message

Shlomo

unread,
Aug 28, 2023, 8:44:24 PM8/28/23
to Django developers (Contributions to Django itself)
I am working on https://code.djangoproject.com/ticket/26836
I created a basic implementation of this with the understanding that many changes may be needed for this to be implemented. https://github.com/django/django/pull/17200.

Currently the way it is implemented a user would in the admin.py file to add a URL to the admin.

from django.contrib import admin
admin.site.register_url("https://djangoproject.com")
# relative urls also work 
# example -> admin.site.register_url("/dashboard")

This would display a Quick links panel above the Recent actions panel with the links. 
Screenshot 2023-08-28 142601.png
To change the text of the link you add a name parameter
from django.contrib import admin
admin.site.register_url("https://djangoproject.com", name="Django")
# or 
admin.site.register_url("https://djangoproject.com""Django")
Screenshot 2023-08-28 143153.png
To specify the location to add this url you add the a location parameter. This will allow any string value so that third parties can add override the template and add additional locations for the url.
Currently the url locations are:
  • links_module (default)
  • navbar
from django.contrib import admin
admin.site.register_url("https://djangoproject.com", name="Django")
admin.site.register_url("https://github.com/django", name="Github", location="navbar")

django.png
I am looking for feedback to solidify the design of this new feature.

Adam Johnson

unread,
Sep 5, 2023, 4:31:09 AM9/5/23
to django-d...@googlegroups.com
I think there’s no need to add a feature here. The userlinks block can be overridden in the admin/base_site.html template to insert extra links, or anything else. Overriding was even mentioned in the commit that added the block, 18 years ago: https://github.com/django/django/commit/43538e78eb98966838168b9d9d84d5f6313e9277 . Similarly, the sidebar block in admin/index.html could be overridden to add links there.

Adding a Python API for links will always be limited because it won’t support arbitrary HTML. Links might need all kinds of customization, such as showing to particular users, adding a 'target' attribute, triggering some javascript, including an icon, ... I think it’s better to keep them as a template-level thing.

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/c3f4359d-ea81-41e8-9187-7c0385019100n%40googlegroups.com.

natali...@gmail.com

unread,
Sep 6, 2023, 8:56:54 AM9/6/23
to Django developers (Contributions to Django itself)
I agree with Adam's assessment. When first reading the proposal, my first thought was that having modifiers such as `location="navbar"` would not scale well. On the one hand, matching against strings could be error prone, and on the other hand, the list of options for a valid location could start getting messy, not to mention if later we also need to add CSS class names or similar the call. Then, it could also get messy with multiple applications registering many links. How are the links sorted? How are they "wrapped" if they are too many? What about duplicate links?

Adding to the above, there are many examples published in online tutorials and related sites that show how to do this links customization if needed, so I think we should not add this to the Django admin.

Natalia.

Shlomo

unread,
Sep 6, 2023, 10:33:49 PM9/6/23
to Django developers (Contributions to Django itself)
You have some great points that I definitely overlooked in the initial implementation. I don't think that overloading the template is a great solution since there are still some features that registered links will add that cannot be done with a simple template override.
  •  It is easier to selectively show links to users based on the request or a custom permission in a method rather than in the template.
  • Currently each app would have to override the navbar userlinks section completely and add their relevant links which would not work if another third party app also overrides the same section. Unless {{ block.super }} is used. {{ block.super }} is not a great option since it would limit links to be added to only the beginning of the block (before VIEW SITE) or the end (after the color theme toggle). It is also close to impossible to set the ordering of links when using the {{ block.super }} approach.
  • No Django apps will add a quick links section to the admin and expect other apps to use that apps Quick Links section. If the Quick Links section is implemented many different apps can utilize this central location to put links. (a setting can be added to disable this)
  • If the app is not sure if the user wants the admin to have the link the app can have the link class available and let the user register it.
The implementation can be changed to use a class-based approach. This will work similar to how the ModelAdmin class works. The target attribute and onClick can be set in the new AdminLink class. For users who need even more control it can have a method .to_html() with can be overridden to display the final html link element. To decide if a link should be shown to a specific user there can be another method called .will_display that will except a request object and will return True or False if that user can see the link or not.
This can even use the Django permissions framework by default to determine if the user should see the link or not. Similar to how the PermissionRequiredMixin works.
You will still be able to override the template if needed the same way as before.
I definitely hear that having modifiers using strings can be error prone and won't scale well but this can be changed to use ENUMS instead.

The user will be able to override any of these methods to customize how the links are displayed.

class RegisterDjango(admin.UrlAdmin):
    menu_order = 5
    on_click = None
    permission_required = ["polls.view_choice", "polls.change_choice"]
    url = "
https://djangoproject.com"
    name = "Django"
    target = "_blank"
    location = admin.Location.QUICK_LINKS

    def get_location(self, request):
        return self.location

    def get_menu_order(self,request):
        return self.menu_order

    def get_on_click(self,request):
        return self.on_click

    def will_display(self,request):
        if request.user.has_perms(self.permission_required):
            return True
        return False

    def get_url(self,request):
        return self.url

    def get_target(self, request):
        return self.target

    def get_name(self, request):
        return self.name

    def to_html(self,request):
        return f'<a href="{self.get_url(request)}" target="{self.get_target(request)}" onClick="{self.get_on_click(request)}">{self.get_name(request)}</a>'


admin.site.register_url(RegisterDjango)

Most apps will likely add additional links to the Quick Links section, so they won't need to be wrapped. This will also cause the navbar not to have so many links. If needed there can be a max links setting that can limit the number of additional links in the navbar.

As far as link ordering I think that using an approach similar to wagtail would be the best option. In the class add a menu_order which will take a number 1 to 999. The lower the number the earlier in the list it will show up.

Please let me know what you think about this.

Mariusz Felisiak

unread,
Sep 7, 2023, 6:10:46 AM9/7/23
to Django developers (Contributions to Django itself)
I'm also -1.

Django Admin is not a universal tool for building an app and adding a new option is always controversial (we already have many of them). There is a way to achieve the same by providing custom templates.

Best,
Mariusz

Matthew Pava

unread,
Sep 7, 2023, 9:34:28 AM9/7/23
to django-d...@googlegroups.com

I reviewed some of the history of this ticket. I tend to agree with the criticisms of adding something akin to an AdminURL to the Django admin.

 

However, the idea of custom views to apps in the admin is an idea that I find appealing. The history of this ticket features a comment from Tim Graham pointing us back to this ticket:

https://code.djangoproject.com/ticket/18665?cversion=1&cnum_hist=3#comment:3

Allowing registering custom admin views with the admin’s index

 

It was opened 11 years ago and last modified 6 years ago. This points us to an external package.

https://github.com/koleror/django-admin-views

 

It looks like it already has URLs implemented in the Django admin interface, so it appears that the volunteer is performing duplicate work. The last update for that project was last year.

 

Our fellows should probably review both tickets to determine if they should be closed.

It does appear that Julien Phalip and Jacob Kaplan-Moss both wanted the features of Django-admin-views inside the admin app. That might be a conversation worth having.

To change the text of the link you add a name parameter

from django.contrib import admin

admin.site.register_url("https://djangoproject.com", name="Django")

# or 

admin.site.register_url("https://djangoproject.com""Django")

To specify the location to add this url you add the a location parameter. This will allow any string value so that third parties can add override the template and add additional locations for the url.

Currently the url locations are:

  • links_module (default)
  • navbar

from django.contrib import admin

admin.site.register_url("https://djangoproject.com", name="Django")
admin.site.register_url(
"https://github.com/django", name="Github", location="navbar")

 

I am looking for feedback to solidify the design of this new feature.

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/c3f4359d-ea81-41e8-9187-7c0385019100n%40googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.

Reply all
Reply to author
Forward
0 new messages