Skip to content

Commit 8039073

Browse files
authored
feat: custom views (#468)
1 parent 4a2792d commit 8039073

File tree

3 files changed

+69
-6
lines changed

3 files changed

+69
-6
lines changed

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
5757
- [Dropdown filters](#dropdown-filters)
5858
- [Numeric filters](#numeric-filters)
5959
- [Date/time filters](#datetime-filters)
60+
- [Custom admin pages](#custom-admin-pages)
6061
- [Nonrelated inlines](#nonrelated-inlines)
6162
- [Display decorator](#display-decorator)
6263
- [Change form tabs](#change-form-tabs)
@@ -621,6 +622,45 @@ class YourModelAdmin(ModelAdmin):
621622
)
622623
```
623624

625+
## Custom admin pages
626+
627+
By default, Unfold provides a basic view mixin which helps with creation of basic views which are part of Unfold UI. The implementation requires creation of class based view inheriting from `unfold.views.UnfoldModelAdminViewMixin`. It is important to add `title` and `permissions_required` properties.
628+
629+
```python
630+
# admin.py
631+
632+
from django.views.generic import TemplateView
633+
from unfold.admin import ModelAdmin
634+
from unfold.views import UnfoldModelAdminViewMixin
635+
636+
637+
class MyClassBasedView(UnfoldModelAdminViewMixin, TemplateView):
638+
title = "Custom Title" # required: custom page header title
639+
permissions_required = () # required: tuple of permissions
640+
template_name = "some/template/path.html"
641+
642+
643+
class CustomAdmin(ModelAdmin):
644+
def get_urls(self):
645+
return super().get_urls() + [
646+
path(
647+
"custom-url-path",
648+
MyClassBasedView.as_view(model_admin=self), # IMPORTANT: model_admin is required
649+
name="custom_name"
650+
),
651+
]
652+
```
653+
654+
The template is straightforward, extend from `unfold/layouts/base.html` and the UI will display all Unfold components like header or sidebar with all menu items. Then all content needs to be located in `content` block.
655+
656+
```django-html
657+
{% extends "unfold/layouts/base.html" %}
658+
659+
{% block content %}
660+
Content here
661+
{% endblock %}
662+
```
663+
624664
## Nonrelated inlines
625665

626666
To display inlines which are not related (no foreign key pointing at the main model) to the model instance in changeform, you can use nonrelated inlines which are included in `unfold.contrib.inlines` module. Make sure this module is included in `INSTALLED_APPS` in settings.py.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{% extends "unfold/layouts/base_simple.html" %}
2+
3+
{% block branding %}
4+
<h1 id="site-name">
5+
<a href="{% url 'admin:index' %}">
6+
{{ site_header|default:_('Django administration') }}
7+
</a>
8+
</h1>
9+
{% endblock %}
10+
11+
{% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}

src/unfold/views.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,25 @@ class UnfoldModelAdminViewMixin(PermissionRequiredMixin):
1010
Prepares views to be displayed in admin
1111
"""
1212

13-
def get_context_data(self, **kwargs) -> Dict[str, Any]:
14-
if "model_admin" not in self.kwargs:
13+
model_admin = None
14+
15+
def __init__(self, model_admin, **kwargs):
16+
self.model_admin = model_admin
17+
super().__init__(**kwargs)
18+
19+
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
20+
if not hasattr(self, "model_admin"):
1521
raise UnfoldException(
1622
"UnfoldModelAdminViewMixin was not provided with 'model_admin' argument"
1723
)
18-
model_admin = self.kwargs["model_admin"]
19-
context_data = super().get_context_data(
20-
**kwargs, **model_admin.admin_site.each_context(self.request)
24+
25+
if not hasattr(self, "title"):
26+
raise UnfoldException(
27+
"UnfoldModelAdminViewMixin was not provided with 'title' attribute"
28+
)
29+
30+
return super().get_context_data(
31+
**kwargs,
32+
**self.model_admin.admin_site.each_context(self.request),
33+
**{"title": self.title},
2134
)
22-
return context_data

0 commit comments

Comments
 (0)