Skip to content

Instantly share code, notes, and snippets.

@hovi
Forked from Vigrond/listlinksmixin.py
Last active August 24, 2020 07:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hovi/2e3a216ecc4be685ec9e0d23b0eb7901 to your computer and use it in GitHub Desktop.
Save hovi/2e3a216ecc4be685ec9e0d23b0eb7901 to your computer and use it in GitHub Desktop.
A Django Admin Mixin that supports foreign key and many-to-many relationship links with list_display_fk_clickthrough and list_display_m2m_clickthrough attribute
class ListDisplayClickthroughMixin(object):
list_display_fk_clickthrough = []
list_display_m2m_clickthrough = []
def __init__(self, *args, **kwargs):
super(ListDisplayClickthroughMixin, self).__init__(*args, **kwargs)
for field in self.list_display_fk_clickthrough or []:
self.bind_field(field, fk_link_fnc)
for field in self.list_display_m2m_clickthrough or []:
self.bind_field(field, m2m_link_fnc)
def bind_field(self, field, bind_func):
if field in self.list_display:
func_name = field + '_link'
setattr(self, func_name, bind_func(field))
self.list_display = [func_name if item ==
field else item for item in self.list_display]
def get_queryset(self, request):
qs = super(ListDisplayClickthroughMixin, self).get_queryset(request)
for field in self.list_display_m2m_clickthrough or []:
fieldparams = {
count_field(field): Count(field, distinct=True)
}
qs = qs.annotate(**fieldparams)
return qs
def fk_link_fnc(field):
def _func(obj):
instance = getattr(obj, field)
if not instance:
return None
return mark_safe(model_change_url(instance))
_func.short_description = field
_func.admin_order_field = field
return _func
def m2m_link_fnc(field):
def _func(obj):
instance = getattr(obj, field)
if not instance:
return None
count = getattr(obj, count_field(field))
kwargs = {
instance.field.get_attname(): obj.pk
}
return mark_safe(model_changelist_url(obj, meta=instance.model._meta, title=count, **kwargs))
_func.short_description = count_field(field)
_func.admin_order_field = count_field(field)
return _func
def count_field(field):
return field + "_count"
def parameters(**kwargs):
if not kwargs:
return ""
return "?" + urlencode(kwargs)
def model_change_url_only(object, meta=None, **kwargs):
meta = meta or object._meta
return reverse('admin:{app}_{model}_change'.format(app=meta.app_label, model=meta.model_name),
args=[object.pk]) + parameters(**kwargs)
def model_changelist_url_only(object=None, meta=None, **kwargs):
meta = meta or object._meta
return reverse('admin:{app}_{model}_changelist'.format(app=meta.app_label, model=meta.model_name)) + parameters(
**kwargs)
def model_change_url(object, meta=None, title=None, **kwargs):
url = model_change_url_only(object, meta=meta, **kwargs)
title = title or unicode(object)
return u'<a href="{url}">{title}</a>'.format(url=url, title=title)
def model_changelist_url(object, meta=None, title=None, **kwargs):
url = model_changelist_url_only(object, meta=meta, **kwargs)
if title is None:
title = unicode(object)
return u'<a href="{url}">{title}</a>'.format(url=url, title=title)
@pymen
Copy link

pymen commented Aug 24, 2020

what does parameters function do? you do not have definition for it.
as i can see it is something '?' + urlencode(kwargs)

@hovi
Copy link
Author

hovi commented Aug 24, 2020

Exactly, for some reason it's missing. Definition is like this (will edit gist):

def parameters(**kwargs):
    if not kwargs:
        return ""
    return "?" + urlencode(kwargs)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment