Skip to content

Commit 3986ffb

Browse files
authored
feat: readonly fields with links (#445)
1 parent 23d8714 commit 3986ffb

File tree

4 files changed

+28
-9
lines changed

4 files changed

+28
-9
lines changed

src/unfold/admin.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from django.contrib.admin import StackedInline as BaseStackedInline
88
from django.contrib.admin import TabularInline as BaseTabularInline
99
from django.contrib.admin import display, helpers
10-
from django.contrib.admin.utils import lookup_field
10+
from django.contrib.admin.utils import lookup_field, quote
1111
from django.contrib.admin.widgets import RelatedFieldWidgetWrapper
1212
from django.core.exceptions import ObjectDoesNotExist
1313
from django.db import models
@@ -33,7 +33,7 @@
3333
from django.shortcuts import redirect
3434
from django.template.defaultfilters import linebreaksbr
3535
from django.template.response import TemplateResponse
36-
from django.urls import URLPattern, path, reverse
36+
from django.urls import NoReverseMatch, URLPattern, path, reverse
3737
from django.utils.html import conditional_escape, format_html
3838
from django.utils.module_loading import import_string
3939
from django.utils.safestring import SafeText, mark_safe
@@ -220,6 +220,22 @@ def contents(self) -> str:
220220
contents = self._preprocess_field(contents)
221221
return contents
222222

223+
def get_admin_url(self, remote_field, remote_obj):
224+
url_name = f"admin:{remote_field.model._meta.app_label}_{remote_field.model._meta.model_name}_change"
225+
try:
226+
url = reverse(
227+
url_name,
228+
args=[quote(remote_obj.pk)],
229+
current_app=self.model_admin.admin_site.name,
230+
)
231+
return format_html(
232+
'<a href="{}" class="text-primary-600 underline">{}</a>',
233+
url,
234+
remote_obj,
235+
)
236+
except NoReverseMatch:
237+
return str(remote_obj)
238+
223239
def _get_contents(self) -> str:
224240
from django.contrib.admin.templatetags.admin_list import _boolean_icon
225241

@@ -239,6 +255,7 @@ def _get_contents(self) -> str:
239255
# ReadOnlyPasswordHashWidget.
240256
if getattr(widget, "read_only", False):
241257
return widget.render(field, value)
258+
242259
if f is None:
243260
if getattr(attr, "boolean", False):
244261
result_repr = _boolean_icon(value)
@@ -255,6 +272,12 @@ def _get_contents(self) -> str:
255272
and value is not None
256273
):
257274
result_repr = self.get_admin_url(f.remote_field, value)
275+
elif isinstance(f, models.URLField):
276+
return format_html(
277+
'<a href="{}" class="text-primary-600 underline">{}</a>',
278+
value,
279+
value,
280+
)
258281
else:
259282
result_repr = display_for_field(value, f, self.empty_value_display)
260283
return conditional_escape(result_repr)

src/unfold/templates/admin/edit_inline/tabular.html

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ <h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 ro
112112
{% if field.is_readonly or not field.field.is_hidden %}
113113
<td{% if field.field.name %} class="field-{{ field.field.name }}{% if field.field.errors|length > 0 %} errors{% endif %}{% if inline_admin_form.original %} p-3 lg:py-3{% else %} py-3{% endif %}{% if field.is_checkbox %} align-middle{% else %} align-top{% endif %} {% if is_last_row and not inline_admin_formset.has_add_permission %}{% if is_last_col %}border-0 {% else %}border-b lg:border-0{% endif %}{% else %}border-b{% endif %} border-gray-200 flex items-center before:capitalize before:content-[attr(data-label)] before:mr-auto before:text-gray-500 before:w-72 lg:before:hidden font-normal px-3 text-left text-sm lg:table-cell dark:border-gray-800 {% if field.field.is_hidden %} !hidden{% endif %}"{% endif %} data-label="{{ field.field.label }}">
114114
{% if field.is_readonly %}
115-
<div class="bg-gray-50 border font-medium max-w-lg px-3 py-2 rounded-md shadow-sm text-gray-500 text-sm truncate whitespace-nowrap dark:border-gray-700 dark:text-gray-400 dark:bg-gray-800">
116-
{{ field.contents }}
117-
</div>
115+
{% include "unfold/helpers/field_readonly_value.html" %}
118116
{% else %}
119117
{{ field.field }}
120118

src/unfold/templates/admin/includes/fieldset.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ <h2 class="bg-gray-100 border border-transparent font-semibold mb-6 px-4 py-3 ro
3838
</div>
3939

4040
{% if field.is_readonly %}
41-
<div class="readonly bg-gray-50 border font-medium max-w-2xl px-3 py-2 rounded-md shadow-sm text-gray-500 text-sm dark:border-gray-700 dark:text-gray-400 dark:bg-gray-800 {% if field.is_json %}truncate whitespace-pre-wrap{% endif %}">{% if field.contents %}{{ field.contents }}{% else %}-{% endif %}</div>
41+
{% include "unfold/helpers/field_readonly_value.html" %}
4242
{% else %}
4343
{{ field.field }}
4444
{% endif %}

src/unfold/templates/unfold/helpers/field_readonly.html

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,5 @@
33
{{ title }}
44
</label>
55

6-
<div class="readonly bg-gray-50 border font-medium max-w-2xl px-3 py-2 rounded-md shadow-sm text-gray-500 text-sm dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400">
7-
{{ value }}
8-
</div>
6+
{% include "unfold/helpers/field_readonly_value.html" %}
97
</div>

0 commit comments

Comments
 (0)