Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
dj-kaos-utils / admin / utils.py
Size: Mime:
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',
)