Last active
May 18, 2020 18:13
-
-
Save Vigrond/ac3c468377ce6d3e53f9b7059fd42569 to your computer and use it in GitHub Desktop.
A Django 2.2 Admin Mixin that supports foreign key relationship links with list_links attribute
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.urls import reverse | |
from django.utils.html import format_html | |
class ListLinksMixin(object): | |
""" | |
Support for list_links attribute. Items in list_links must also be in list_display | |
Usage to make 'fieldTwo' a link: | |
list_display = ('fieldOne', 'fieldTwo',) | |
list_links = ('fieldTwo',) | |
""" | |
list_links = [] | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
if self.list_links: | |
for field in self.list_links: | |
if field in self.list_display: | |
func_name = field + '_link' | |
setattr(self, func_name, self._generate_link_func(field)) | |
self.list_display = [func_name if item == | |
field else item for item in self.list_display] | |
def _generate_link_func(self, field): | |
def _func(item): | |
instance = getattr(item, field) | |
if not instance: | |
return None | |
url = reverse( | |
f'admin:{instance._meta.app_label}_{instance._meta.model_name}_change', args=[instance.pk]) | |
return format_html(f'<a href="{url}">{instance}</a>') | |
_func.short_description = field | |
_func.admin_order_field = field | |
return _func |
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.list_links:
for field in self.list_links:
func_name = field + '_link'
setattr(self, func_name, self._generate_link_func(field))
if field in self.list_display:
self.list_display = [
func_name if item == field
else item for item in self.list_display
]
if field in self.readonly_fields:
self.readonly_fields = [
func_name if item == field
else item for item in self.readonly_fields
]
This change allows the links to be in readonly_fields as well (either or both), which is nice if your list_display is already crowded and you only want it if the viewer is viewing the particular model. I also find it disorienting when something is in list_display and not in the model view.
It probably could be a bit cleaner than if-ing each fields list, but it works great.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for this. It's unbelievable that django doesn't support this out of the box.