#5943 - Permits template tags to be used in the plugins namespace for certain filters

This commit is contained in:
Daniel Sheppard 2021-03-10 15:05:57 -06:00
parent c072ba088f
commit ba338bbb3f
6 changed files with 81 additions and 15 deletions

View File

@ -149,20 +149,15 @@ class ButtonsColumn(tables.TemplateColumn):
attrs = {'td': {'class': 'text-right text-nowrap noprint'}} attrs = {'td': {'class': 'text-right text-nowrap noprint'}}
# Note that braces are escaped to allow for string formatting prior to template rendering # Note that braces are escaped to allow for string formatting prior to template rendering
template_code = """ template_code = """
{{% load buttons %}}
{{% if "changelog" in buttons %}} {{% if "changelog" in buttons %}}
<a href="{{% url '{app_label}:{model_name}_changelog' pk=record.pk %}}" class="btn btn-default btn-xs" title="Change log"> {{% tr_changelog_button record %}}
<i class="mdi mdi-history"></i>
</a>
{{% endif %}} {{% endif %}}
{{% if "edit" in buttons and perms.{app_label}.change_{model_name} %}} {{% if "edit" in buttons and perms.{app_label}.change_{model_name} %}}
<a href="{{% url '{app_label}:{model_name}_edit' pk=record.pk %}}?return_url={{{{ request.path }}}}{{{{ return_url_extra }}}}" class="btn btn-xs btn-warning" title="Edit"> {{% tr_edit_button record return_url_extra %}}
<i class="mdi mdi-pencil"></i>
</a>
{{% endif %}} {{% endif %}}
{{% if "delete" in buttons and perms.{app_label}.delete_{model_name} %}} {{% if "delete" in buttons and perms.{app_label}.delete_{model_name} %}}
<a href="{{% url '{app_label}:{model_name}_delete' pk=record.pk %}}?return_url={{{{ request.path }}}}{{{{ return_url_extra }}}}" class="btn btn-xs btn-danger" title="Delete"> {{% tr_delete_button record return_url_extra %}}
<i class="mdi mdi-trash-can-outline"></i>
</a>
{{% endif %}} {{% endif %}}
""" """

View File

@ -0,0 +1,3 @@
<a href="{{ url }}" class="btn btn-default btn-xs" title="Change log">
<i class="mdi mdi-history"></i>
</a>

View File

@ -0,0 +1,3 @@
<a href="{{ url }}" class="btn btn-danger btn-xs" title="Change log">
<i class="mdi mdi-trash-can-outline"></i>
</a>

View File

@ -0,0 +1,3 @@
<a href="{{ url }}" class="btn btn-warning btn-xs" title="Change log">
<i class="mdi mdi-pencil"></i>
</a>

View File

@ -4,22 +4,71 @@ from django.urls import reverse
from extras.models import ExportTemplate from extras.models import ExportTemplate
from utilities.utils import prepare_cloned_fields from utilities.utils import prepare_cloned_fields
from .helpers import _resolve_namespace
register = template.Library() register = template.Library()
def _get_listviewname(instance):
app_label = _resolve_namespace(instance)
return f'{app_label}:{instance._meta.model_name}_list'
def _get_viewname(instance, action): def _get_viewname(instance, action):
""" """
Return the appropriate viewname for adding, editing, or deleting an instance. Return the appropriate viewname for adding, editing, or deleting an instance or viewing.
""" """
# Validate action # Validate action
assert action in ('add', 'edit', 'delete') assert action in ('add', 'edit', 'delete')
viewname = "{}:{}_{}".format( app_label = _resolve_namespace(instance)
instance._meta.app_label, instance._meta.model_name, action viewname = f'{app_label}:{instance._meta.model_name}_{action}'
)
return viewname return viewname
#
# Table buttons
#
@register.inclusion_tag('buttons/tr_edit.html')
def tr_edit_button(instance, extra=None):
viewname = _get_viewname(instance, 'edit')
base_url = reverse(_get_listviewname(instance))
url = reverse(viewname, kwargs={'pk': instance.pk})
url = f'{url}?return_url={base_url}'
if extra is not None:
url = f'{url}{extra}'
return {
'url': url,
}
@register.inclusion_tag('buttons/tr_delete.html')
def tr_delete_button(instance, extra=None):
viewname = _get_viewname(instance, 'delete')
base_url = reverse(_get_listviewname(instance))
url = reverse(viewname, kwargs={'pk': instance.pk})
url = f'{url}?return_url={base_url}'
if extra is not None:
url = f'{url}{extra}'
return {
'url': url,
}
@register.inclusion_tag('buttons/tr_changelog.html')
def tr_changelog_button(instance):
app_label = _resolve_namespace(instance)
viewname = f'{app_label}:{instance._meta.model_name}_changelog'
url = reverse(viewname, kwargs={'pk': instance.pk})
return {
'url': url,
}
# #
# Instance buttons # Instance buttons

View File

@ -4,6 +4,7 @@ import re
import yaml import yaml
from django import template from django import template
from django.apps import apps
from django.conf import settings from django.conf import settings
from django.urls import NoReverseMatch, reverse from django.urls import NoReverseMatch, reverse
from django.utils.html import strip_tags from django.utils.html import strip_tags
@ -13,9 +14,21 @@ from markdown import markdown
from utilities.forms import TableConfigForm from utilities.forms import TableConfigForm
from utilities.utils import foreground_color from utilities.utils import foreground_color
from extras.plugins import PluginConfig
register = template.Library() register = template.Library()
def _resolve_namespace(instance):
"""
Get the appropriate namespace for the app based on whether it is a Plugin or base application
"""
app = apps.get_app_config(instance._meta.app_label)
if isinstance(app, PluginConfig):
return f'plugins:{app.label}'
return f'{app.label}'
# #
# Filters # Filters
# #
@ -80,7 +93,7 @@ def viewname(model, action):
""" """
Return the view name for the given model and action. Does not perform any validation. Return the view name for the given model and action. Does not perform any validation.
""" """
return f'{model._meta.app_label}:{model._meta.model_name}_{action}' return f'{_resolve_namespace(model)}:{model._meta.model_name}_{action}'
@register.filter() @register.filter()
@ -88,7 +101,7 @@ def validated_viewname(model, action):
""" """
Return the view name for the given model and action if valid, or None if invalid. Return the view name for the given model and action if valid, or None if invalid.
""" """
viewname = f'{model._meta.app_label}:{model._meta.model_name}_{action}' viewname = f'{_resolve_namespace(model)}:{model._meta.model_name}_{action}'
try: try:
# Validate and return the view name. We don't return the actual URL yet because many of the templates # Validate and return the view name. We don't return the actual URL yet because many of the templates
# are written to pass a name to {% url %}. # are written to pass a name to {% url %}.