-
-
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
This file contains 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
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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Exactly, for some reason it's missing. Definition is like this (will edit gist):