1

Suppose I have a model of Category, and it has been declared in admin.py.

There are two things that I want to do using Django template overriding.

  • Add a button on the right near "Add Category +" which is visible only on the Category List page and takes me to another URL.
  • Overriding URLs of Category object so that clicking on each individual category on the list takes to the respective URLs
# models.py

class Category(models.Model):
    name = models.CharField(max_length=50, null=True, blank=False)
    LANGUAGE_ENGLISH = 'en'
    LANGUAGE_FRENCH = 'fr'

    LANGUAGES = ((LANGUAGE_ENGLISH, 'English'),(LANGUAGE_FRENCH, 'French'),)

    language = models.CharField(max_length=12, default=LANGUAGE_ENGLISH, choices=LANGUAGES, blank=False)
    created_at = models.DateTimeField(auto_now_add=True)
# admin.py

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ('name', 'language', 'created_at')
    list_filter = ('created_at', 'language')
    search_fields = ('name',)
    date_hierarchy = 'created_at'
    ordering = ['-created_at']

Category in the admin panel Category in the admin panel Here, clicking on Lifestyle or Travel should take me to two external urls.

1 Answers1

2

First solution:

override list_display_links and change your field manually

It's a two steps process. First, we need to change get_list_display_links default behavior.

Looking at django's doc and source you will realize it will end up using first item in list_display. In your admin class:

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ('name', 'language', 'created_at')
    list_filter = ('created_at', 'language')
    list_display_links = [] #< With this, you still can add up a link to your original admin
    search_fields = ('name',)
    date_hierarchy = 'created_at'
    ordering = ['-created_at']

    def get_list_display_links(self, request, list_display):
        """
        Return a sequence containing the fields to be displayed as links
        on the changelist. The list_display parameter is the list of fields
        returned by get_list_display().
        """
        if self.list_display_links or self.list_display_links is None or not list_display:
            # We make sure you still add your admin's links if you explicitly declare `list_display_links`
            return self.list_display_links 
        else:
            # We return empty list instead of `list_display[:1]`
            # if no `list_display_links` is provided.
            return []

Then using this answer, you can make any column customized.

Second solution:

Handle change view yourself

In your admin class:

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
   #... same things as you have

   def change_view(self, request, object_id, form_url="", extra_context=None):
       #Now, you can do pretty much whatever: it's a function based view!

I'd recommend the first one as I believe default admin's change_view is always usefull.

Community
  • 1
  • 1
Julien Kieffer
  • 1,116
  • 6
  • 16
  • It did not work for me. I added the line `list_display_links = []` defined `get_list_display_links` exactly like showed above. Then, according to the second answer defined `name(self,obj)` to return the html element. What do you think I did wrong? – Yash Suryavanshi Oct 17 '19 at 11:36
  • Without thinking about the `name(self,obj)` part: Do you have a link using just the `list_display_links` ? – Julien Kieffer Oct 17 '19 at 11:47
  • Please rephrase. – Yash Suryavanshi Oct 17 '19 at 11:58
  • Forget about the `html` markup. When I add `list_display_links = []` and `get_list_display_links` only, the origin link on the first column is not here anymore. Is it OK on your end? – Julien Kieffer Oct 17 '19 at 14:11
  • Your suggested code works well and is an acceptable solution. One needs to add a new field name for step 2. It would be nice if the existing field's link could be changed. Also, could you bother dumbing down get_list_display_links(). It would be a great help to understand. – Yash Suryavanshi Oct 17 '19 at 21:22
  • I've added explanations about `get_list_display_links` and added a second solution. – Julien Kieffer Oct 18 '19 at 11:33