WhenDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/rahul-baberwal/django-var-cms/llms.txt
Use this file to discover all available pages before exploring further.
var_cms starts up, it automatically iterates every entry in INSTALLED_APPS and attempts to import {app}.var_cms_admin for each app. This means you never need to manually wire up any import — simply create the file in your app directory and django-var-cms will discover and load it at startup, registering all of your models with the global var_cms_site registry.
Creating var_cms_admin.py
Create the file
Inside any Django app that you want to expose in the CMS, create a file named
var_cms_admin.py at the root of that app:Import the registry and base class
At the top of your new file, import the global site instance and the base admin class:
Class Attributes Reference
Every attribute onVarCMSModelAdmin is optional — sensible defaults are applied automatically. The table below covers all configuration options.
| Attribute | Type | Default | Description |
|---|---|---|---|
list_display | list[str] | First 6 model fields | Column names shown in the list view table |
list_filter | list[str] | [] | Fields rendered as sidebar filter widgets |
search_fields | list[str] | [] | Fields searched with a case-insensitive icontains lookup |
ordering | list[str] | [] | Default queryset ordering (prefix - for descending) |
list_per_page | int | 25 | Number of rows per page in the list view |
list_select_related | bool | False | Call select_related() on the queryset to reduce N+1 queries |
list_image_width | int | 38 | Pixel width of image thumbnails in list columns |
list_image_height | int | 38 | Pixel height of image thumbnails in list columns |
readonly_fields | list[str] | [] | Fields always displayed but never editable |
exclude_fields | list[str] | [] | Fields hidden from the form entirely |
html_fields | list[str] | [] | TextField names that get a Quill.js rich text editor |
regex_validators | dict[str, tuple] | {} | Per-field (pattern, message) tuples applied client-side and server-side |
form_field_widths | dict[str, str] | {} | Named grid-width preset per field ("full", "half", etc.) |
form_field_rows | list[list[str]] | [] | Groups of fields sharing a single visual row with equal column widths |
form_field_widgets | dict[str, str] | {} | Custom widget type per field ("select_search", "multiselect", etc.) |
form_widget_classes | dict[str, str] | {} | CSS classes appended to the input/select/textarea element |
form_field_placeholders | dict[str, str] | {} | HTML placeholder attribute per field |
form_field_help_texts | dict[str, str] | {} | Help text shown beneath each field (overrides model-level help_text) |
form_field_classes | dict[str, str] | {} | CSS classes added to the field’s wrapper <div> |
form_field_styles | dict[str, str] | {} | Inline CSS styles added to the field’s wrapper <div> |
icon | str | "" | Lucide icon name displayed beside the model in the sidebar and dashboard |
dashboard_card | bool | False | Whether this model appears as a card on the dashboard |
card_buttons | list[dict] | [] | Navigation buttons on the dashboard card (see Custom Actions) |
custom_object_actions | list[dict] | [] | Per-object action buttons on list and detail views (see Custom Actions) |
The icon attribute
The icon value is a Lucide icon name — the same string you would use in <i data-lucide="...">. You can browse the full icon catalogue at lucide.dev. Common examples for CMS models:
The dashboard_card attribute
By default every registered model is hidden from the dashboard (dashboard_card = False). Set it to True to show a stats card for that model on the home screen:
settings.py without touching individual admin classes:
Unregistering a Model
Callvar_cms_site.unregister() to remove a previously registered model. This is useful when you want to override a registration made in a third-party app:
save_model() and delete_model() Hooks
VarCMSModelAdmin exposes two lifecycle hooks that you can override for custom save or delete behaviour.
save_model(request, obj, form, change)
Called whenever an object is saved (both create and update). The default implementation checks whether the model has a slug field and, if it is empty, auto-generates a slug from the first non-empty value found in title, name, or headline, then calls obj.save().
| Parameter | Description |
|---|---|
request | The current HttpRequest |
obj | The unsaved model instance |
form | The bound ModelForm instance |
change | True when updating an existing record; False on create |
delete_model(request, obj)
Called when an object is deleted. The default implementation calls obj.delete().
Complete Example
The following example is taken directly from the demo app and showsCategoryAdmin and ArticleAdmin with realistic field configurations, permissions, and lifecycle hooks.
- models.py
- var_cms_admin.py