Skip to content

Commit

Permalink
Use templates to render admin values
Browse files Browse the repository at this point in the history
  • Loading branch information
davegaeddert committed Jan 18, 2024
1 parent 6f4994e commit 27e4649
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 34 deletions.
2 changes: 1 addition & 1 deletion bolt-staff/bolt/admin/templates/admin/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ <h1 class="text-2xl font-semibold">Fields</h1>
<dl class="grid grid-cols-2 mt-6 text-sm">
{% for field in fields %}
<dt class="font-mono bg-gray-100 rounded inline-block px-0.5">{{ field }}</dt>
<dd>{{ get_object_field(object, field) or "Empty" }}</dd>
<dd>{{ get_field_value(object, field) }}</dd>
{% endfor %}
</dl>
</admin.Card>
Expand Down
22 changes: 6 additions & 16 deletions bolt-staff/bolt/admin/templates/admin/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,22 +121,12 @@
{% endif %}

{% for field in fields %}
<td>
<div class="flex">
{% set value = get_object_field(object, field) %}
{%- if value is true -%}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-3 h-3 text-green-500 bi bi-check-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
</svg>
{%- elif value is false -%}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-3 h-3 text-red-600 bi bi-x-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z"/>
</svg>
{%- else -%}
{{ value }}
{%- endif %}
</div>
</td>
<td>
<div class="flex">
{% set value = get_field_value(object, field) %}
{% include get_field_value_template(object, field, value) with context %}
</div>
</td>
{% endfor %}

{% set detail_url = get_detail_url(object) %}
Expand Down
1 change: 1 addition & 0 deletions bolt-staff/bolt/admin/templates/admin/values/UUID.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<code class="px-1 text-xs bg-gray-100 rounded">{{ value }}</code>
9 changes: 9 additions & 0 deletions bolt-staff/bolt/admin/templates/admin/values/bool.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{%- if value -%}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-3 h-3 text-green-500 bi bi-check-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
</svg>
{%- else -%}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-3 h-3 text-red-600 bi bi-x-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z"/>
</svg>
{%- endif %}
1 change: 1 addition & 0 deletions bolt-staff/bolt/admin/templates/admin/values/datetime.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<span class="tabular-nums" title="{{ value.isoformat() }}">{{ value|localtime|strftime("%Y-%m-%d %-I:%M:%S %p") }}</span>
1 change: 1 addition & 0 deletions bolt-staff/bolt/admin/templates/admin/values/default.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{ value }}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<span title="{{ value }}">{{ object['get_' + field + '_display']() }}</span>
27 changes: 18 additions & 9 deletions bolt-staff/bolt/admin/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ def get_context(self):
context["table_style"] = getattr(self, "_table_style", "default")

context["get_object_pk"] = self.get_object_pk
context["get_object_field"] = self.get_object_field
context["get_field_value"] = self.get_field_value
context["get_field_value_template"] = self.get_field_value_template

context["get_create_url"] = self.get_create_url
context["get_detail_url"] = self.get_detail_url
Expand Down Expand Up @@ -226,32 +227,40 @@ def get_actions(self) -> dict[str]:
def get_filters(self) -> list[str]:
return self.filters.copy() # Avoid mutating the class attribute itself

def get_object_field(self, obj, field: str):
def get_field_value(self, obj, field: str):
# Try basic dict lookup first
if field in obj:
return obj[field]

# Try dot notation
if "." in field:
field, subfield = field.split(".", 1)
return self.get_object_field(obj[field], subfield)
return self.get_field_value(obj[field], subfield)

# Try regular object attribute
return getattr(obj, field)

def get_object_pk(self, obj):
try:
return self.get_object_field(obj, "pk")
return self.get_field_value(obj, "pk")
except AttributeError:
return self.get_object_field(obj, "id")
return self.get_field_value(obj, "id")

def get_field_value_template(self, obj, field: str, value):
type_str = type(value).__name__.lower()
return [
f"admin/values/{type_str}.html", # Create a template per-type
f"admin/values/{field}.html", # Or for specific field names
"admin/values/default.html",
]

def get_create_url(self) -> str | None:
return None

def get_detail_url(self, object) -> str | None:
def get_detail_url(self, obj) -> str | None:
return None

def get_update_url(self, object) -> str | None:
def get_update_url(self, obj) -> str | None:
return None


Expand All @@ -261,7 +270,7 @@ class AdminDetailView(AdminView, DetailView):

def get_context(self):
context = super().get_context()
context["get_object_field"] = self.get_object_field
context["get_field_value"] = self.get_field_value
return context

def get_template_names(self) -> list[str]:
Expand All @@ -274,7 +283,7 @@ def get_template_names(self) -> list[str]:

return super().get_template_names()

def get_object_field(self, obj, field: str):
def get_field_value(self, obj, field: str):
return getattr(obj, field)


Expand Down
20 changes: 12 additions & 8 deletions bolt-staff/bolt/admin/views/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ def get_model_field(instance, field):

return result

# Automatically call get_FOO_display() if it exists
if display := getattr(instance, f"get_{field}_display", None):
return display()

return getattr(instance, field)


Expand Down Expand Up @@ -97,8 +93,16 @@ def search_queryset(self, queryset):

return queryset

def get_object_field(self, object, field: str):
return get_model_field(object, field)
def get_field_value(self, obj, field: str):
return get_model_field(obj, field)

def get_field_value_template(self, obj, field: str, value):
templates = super().get_field_value_template(obj, field, value)
if hasattr(obj, f"get_{field}_display"):
# Insert before the last default template,
# so it can still be overriden by the user
templates.insert(-1, "admin/values/get_display.html")
return templates


class AdminModelDetailView(AdminDetailView):
Expand All @@ -124,8 +128,8 @@ def get_context(self):
]
return context

def get_object_field(self, object, field: str):
return get_model_field(object, field)
def get_field_value(self, obj, field: str):
return get_model_field(obj, field)

def get_object(self):
return self.model.objects.get(pk=self.url_kwargs["pk"])
Expand Down

0 comments on commit 27e4649

Please sign in to comment.