Repository URL to install this package:
Version:
0.2.0a4 ▾
|
from django.urls import NoReverseMatch, reverse
from pygments.lexers.data import JsonLexer # NoQA: Pycharm trips over this import
from dj_kaos_utils.html import render_anchor
def get_admin_link(obj):
"""
Return the admin change page link for the given object, or None if the link cannot be generated.
:param obj: the object for which to get the admin change page link
:type obj: django model instance
:return: the admin change page link if it exists or None otherwise
:rtype: str or None
:raises: `NoReverseMatch` if the admin change URL does not exist for the given object
Example:
>>> class MyModel(models.Model):
>>> def get_absolute_url(self):
>>> return get_admin_link(self)
"""
opts = obj._meta
try:
return reverse(f'admin:{opts.app_label}_{opts.model_name}_change', args=(obj.id,))
except NoReverseMatch:
return None
def render_admin_link(obj, **kwargs):
"""
Return marked-as-safe html containing an anchor tag linking to the admin change page of the object. If the object
doesn't have an admin change page, return the string representation of the object
:param obj: the model instance to grab the link for
:param kwargs: extra kwargs to pass to `render_anchor`
:return: marked-as-safe html of the anchor tag
Example:
>>> class MyModelAdmin(admin.ModelAdmin):
>>> def parent_display(self, obj):
>>> return render_admin_link(obj.parent)
"""
admin_link = get_admin_link(obj)
if admin_link:
return render_anchor(admin_link, str(obj), **kwargs)
else:
return str(obj)
def instance_action(function):
"""
Decorator to call a model method as an admin action.
"""
def call_action(self, request, instance):
name = function.__name__
method = getattr(instance, name)
function(self, request, method())
return call_action
def qs_action(function, method_name=None):
"""
Decorator to call a queryset method as an admin action. Decorate your admin action with ``@qs_action`` and you won't
need to write an implementation for your action. The decorator automatically pulls the right queryset method from
the action method name.
The signature of the decorated admin method changes from ``(self, request, queryset)`` to
``(self, request, results)``. `results` here is the return value of calling the queryset method.
:param function: the function that is decorated
:param method_name: the name of the queryset method to call. By default, the name of the :attr:`function`.
Example:
>>> class MyModelAdmin(admin.ModelAdmin):
>>> @qs_action # or @qs_action(method_name='publish')
>>> def publish(self, request, results):
>>> # the third arg is now `results` which is the return value of the queryset method.
>>> self.message_user(request, f"Published {results} objects.", messages.SUCCESS)
"""
method_name = method_name if method_name is not None else function.__name__
def call_action(self, request, queryset):
qs_method = getattr(queryset, method_name)
results = qs_method()
function(self, request, results)
return call_action
def render_admin_popup_link(
url: str,
params: dict,
label: str,
class_names="",
):
params_str = '&'.join(f'{k}={v}' for k, v in {**params, '_popup': '1'}.items())
return render_anchor(
href=url + '?' + params_str,
children=label,
new_tab=False,
attrs={
'data-popup': 'yes',
'class': f'related-widget-wrapper-link {class_names}',
}
)
__all__ = (
'get_admin_link',
'render_admin_link',
'instance_action',
'qs_action',
'render_admin_popup_link',
)