demo-views
Simplifies creating demo pages in django-mvp by using standardized view classes and template inheritance.
Install
mkdir -p .claude/skills/demo-views && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/10300" && unzip -o skill.zip -d .claude/skills/demo-views && rm skill.zipInstalls to .claude/skills/demo-views
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Guide for creating demo views in the django-mvp Demo App. Use when adding new demo pages to showcase components, layouts, or features — covers view creation, template structure, URL wiring, and sidebar menu registration. Emphasizes single configurable view classes with .as_view() attribute overrides instead of duplicating views.Key capabilities
- →Create demo views
- →Wire URL patterns
- →Register sidebar menus
- →Configure layout variations
How it works
It standardizes demo page creation using configurable view classes and template blocks.
Inputs & outputs
When to use demo-views
- →Adding new component demos
- →Configuring layout variations for demo pages
- →Wiring new URL patterns in the demo app
About this skill
Creating Demo Views for the Demo App
The demo/ app demonstrates django-mvp features. Each demo page follows a consistent pattern: one configurable view class, a template extending base.html, a URL pattern (with optional .as_view() overrides), and a sidebar menu entry.
File Locations
| File | Purpose |
|---|---|
demo/views.py | View classes |
demo/urls.py | URL patterns |
demo/menus.py | Sidebar menu items |
demo/templates/demo/<name>.html | Page templates |
demo/templates/base.html | Project-level base (extends mvp/base.html) |
Step 1: Create the View
Always include LayoutConfigMixin
Every demo view must inherit LayoutConfigMixin first — it reads query parameters for interactive layout configuration (fixed sidebar/header/footer, breakpoints, etc.):
from django.views.generic import TemplateView
from demo.views import LayoutConfigMixin
class MyDemoView(LayoutConfigMixin, TemplateView):
template_name = "demo/my_demo.html"
One View, Many Configurations — Use .as_view() Overrides
Do NOT create separate view classes for minor variations. Instead, define one view with configurable class attributes and override them in urls.py:
# views.py — ONE view class
class WidgetDemoView(LayoutConfigMixin, TemplateView):
template_name = "demo/widget_demo.html"
variant = "default"
show_icons = True
# urls.py — multiple URL patterns with .as_view() overrides
urlpatterns = [
path("widgets/", WidgetDemoView.as_view(), name="widget_demo"),
path("widgets/compact/", WidgetDemoView.as_view(variant="compact"), name="widget_demo_compact"),
path("widgets/no-icons/", WidgetDemoView.as_view(show_icons=False), name="widget_demo_no_icons"),
]
Only create a separate view class when it needs different methods or significantly different behavior.
View Patterns by Django Generic View Type
TemplateView — simplest; for static demos or component showcases:
class MyDemoView(LayoutConfigMixin, TemplateView):
template_name = "demo/my_demo.html"
ListView — for list/grid demos; combine with MVPListViewMixin and PageModifierMixin:
from mvp.views import MVPListViewMixin, PageModifierMixin
class MyListDemo(LayoutConfigMixin, PageModifierMixin, MVPListViewMixin, ListView):
model = MyModel
template_name = "mvp/list_view.html"
list_item_template = "cards/my_card.html"
paginate_by = 12
grid = {"cols": 1, "md": 2} # Override via .as_view(grid={...})
search_fields = ["name", "description"] # Optional
order_by = [("name", "Name (A-Z)"), ("-name", "Name (Z-A)")] # Optional
CreateView / FormView — for form demos:
class MyFormDemo(LayoutConfigMixin, CreateView):
model = MyModel
fields = ["name", "description"]
template_name = "mvp/form_view.html"
extra_context = {"page_title": "My Form Demo"}
FilterView — for filterable list demos (django-filter):
from django_filters.views import FilterView
class MyFilterDemo(LayoutConfigMixin, PageModifierMixin, MVPListViewMixin, FilterView):
model = MyModel
template_name = "mvp/list_view.html"
list_item_template = "cards/my_card.html"
filterset_fields = ["category", "status"]
SingleTableView — for django-tables2 demos:
from django_tables2 import SingleTableView
class MyTableDemo(LayoutConfigMixin, SingleTableView):
model = MyModel
table_class = MyTable
template_name = "demo/my_table.html"
paginate_by = 25
Adding Extra Context
Use get_context_data when the template needs dynamic data. Always call super():
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["sample_items"] = [...]
return context
For static context, prefer extra_context:
class MyDemo(LayoutConfigMixin, TemplateView):
template_name = "demo/my_demo.html"
extra_context = {"page_title": "My Demo"}
Step 2: Create the Template
Templates live in demo/templates/demo/ and extend base.html.
Block Hierarchy
base.html (extends mvp/base.html, overrides "app")
├── navbar_widgets — navbar widget components (top-right)
├── main — wraps <c-page>; override to replace entire inner layout
│ ├── toolbar
│ │ └── toolbar_content
│ │ ├── breadcrumbs — add breadcrumb items
│ │ └── toolbar_widgets — toolbar actions (right side)
│ ├── content — main page content ← MOST COMMON OVERRIDE
│ └── footer — page footer
├── app_footer — app-level footer
└── extra_js — additional scripts
Typical Template (override breadcrumbs + content)
Most demo templates only need two blocks:
{% extends "base.html" %}
{% block breadcrumbs %}
<c-breadcrumbs.item text="My Demo" />
{% endblock breadcrumbs %}
{% block content %}
<div class="container-fluid">
<h2>My Demo</h2>
<!-- demo content here -->
</div>
{% endblock content %}
When to Override Other Blocks
| Block | Override when... |
|---|---|
breadcrumbs | Always — add the page breadcrumb |
content | Always — the main demo content |
toolbar_widgets | Page needs action buttons in the toolbar |
footer | Page needs a custom footer or no footer |
main | Page needs to replace the entire <c-page> structure (rare) |
app (from mvp/base.html) | Page needs to reconfigure <c-app> props like breakpoints (rare) |
extra_js | Page needs additional JavaScript |
navbar_widgets | Page needs custom navbar widgets (rare — usually keep defaults) |
Template with Toolbar Widgets
{% extends "base.html" %}
{% block breadcrumbs %}
<c-breadcrumbs.item text="My Demo" />
{% endblock breadcrumbs %}
{% block toolbar_widgets %}
<button class="btn btn-sm btn-primary">Action</button>
{% endblock toolbar_widgets %}
{% block content %}
<div class="container-fluid">
<!-- content -->
</div>
{% endblock content %}
Step 3: Add the URL Pattern
In demo/urls.py, add the path. Import only what's needed:
from .views import MyDemoView
urlpatterns = [
# ... existing patterns ...
path("my-demo/", MyDemoView.as_view(), name="my_demo"),
]
For configuration variants, override attributes via .as_view():
urlpatterns = [
path("my-demo/", MyDemoView.as_view(), name="my_demo"),
path("my-demo/alt/", MyDemoView.as_view(variant="alt"), name="my_demo_alt"),
]
Step 4: Add the Sidebar Menu Entry
In demo/menus.py, add items using AppMenu.extend() or mutate existing groups. Read the sidebar-menu skill for full reference.
Adding a standalone menu item
AppMenu.extend([
MenuItem(
name="my_demo",
view_name="my_demo",
extra_context={"label": "My Demo", "icon": "star"},
),
])
Adding to an existing MenuGroup
Use AppMenu.get() to find a group and add children:
group = AppMenu.get("list_views")
if group:
group.add(MenuItem(
name="my_list_variant",
view_name="my_list_variant",
extra_context={"label": "My Variant", "icon": "circle"},
))
Creating a new MenuGroup for related demos
MenuGroup(
name="my_demos_section",
extra_context={"label": "MY DEMOS"},
children=[
MenuItem(name="demo_a", view_name="demo_a",
extra_context={"label": "Demo A", "icon": "circle"}),
MenuItem(name="demo_b", view_name="demo_b",
extra_context={"label": "Demo B", "icon": "circle"}),
],
)
Checklist
Before considering a demo view complete, verify:
- ✅ View inherits
LayoutConfigMixinas first parent - ✅ Only ONE view class exists per feature (variants use
.as_view()overrides) - ✅ Template extends
base.htmland overridesbreadcrumbs+contentat minimum - ✅ URL pattern added in
demo/urls.pywith a named route - ✅ Sidebar menu entry added in
demo/menus.py(standalone or within a group) - ✅ View name in
MenuItemmatches the URL pattern name
When not to use it
- →Non-django-mvp projects
- →Projects without demo app
Prerequisites
Limitations
- →Requires LayoutConfigMixin
- →Limited to demo app structure
How it compares
It uses single configurable view classes instead of duplicating views for variations.
Compared to similar skills
demo-views side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| demo-views (this skill) | 0 | 1mo | No flags | Intermediate |
| django-pro | 20 | 4mo | No flags | Intermediate |
| python-configuration | 5 | 2mo | Review | Beginner |
| django-patterns | 3 | 4mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
django-pro
sickn33
Master Django 5.x with async views, DRF, Celery, and Django Channels. Build scalable web applications with proper architecture, testing, and deployment. Use PROACTIVELY for Django development, ORM optimization, or complex Django patterns.
python-configuration
wshobson
Python configuration management via environment variables and typed settings. Use when externalizing config, setting up pydantic-settings, managing secrets, or implementing environment-specific behavior.
django-patterns
affaan-m
Django架构模式、使用DRF的REST API设计、ORM最佳实践、缓存、信号、中间件以及生产级Django应用程序。
django-insights
carlosapgomes
Diagnóstico de saúde para projetos Django: performance, segurança e arquitetura.
python-pro
pikakit
>-
django-flask-patterns
sraloff
Models/views/templates (Django), blueprints (Flask), migrations.