A modern, role-based Django CMS registry with Tailwind CSS support and rich media previews
Project description
django-var-cms
A modern, highly customizable administrative Control Panel and CMS registry for Django projects. Built with premium glassmorphic aesthetics, role-based security, and rich media processing.
Created by Rahul Baberwal.
🚀 Key Features
- 🎨 Modern Design System: Responsive glassmorphic layout, collapsible navigation sidebar with
localStoragepersistent state, and custom HSL accent color configurations. - 🔑 Role & User Permissions: Manage fine-grained view, list, edit, add, and delete actions matching Django Groups or specific user accounts.
- 📝 HTML Editor: Integrated Quill.js rich text editor out of the box.
- ✅ Regex Field Validation: Easily enforce custom regular expression patterns both client-side and server-side.
- 🖼️ Media Previews & Image Cropper:
- Modal-based previews for images, video, audio, and PDFs.
- Built-in Image Cropper (rotate, flip, custom aspect ratio crops).
- API endpoints for media conversion (JPEG, PNG, WebP, WAV, MP3, MP4).
⚙️ Setup & Installation
1. Install Dependencies
Install django-var-cms along with required media dependencies and optional Tailwind CSS support:
# Standard installation
pip install django-var-cms pillow whitenoise
# With Tailwind CSS support
pip install django-var-cms[tailwind] pillow whitenoise
# Using uv
uv add django-var-cms pillow whitenoise
# Using uv with Tailwind CSS
uv add django-var-cms[tailwind] pillow whitenoise
2. Configure settings.py
Register "var_cms" in your Django INSTALLED_APPS and specify static/media paths:
# settings.py
INSTALLED_APPS = [
# ... Django standard apps
"var_cms",
# "demo", (optional demo app)
]
# Media settings for handling file uploads/crops
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"
# Static files settings
STATIC_URL = "/static/"
STATICFILES_DIRS = [BASE_DIR / "static"]
STATIC_ROOT = BASE_DIR / "staticfiles"
# Redirect paths for authentication
LOGIN_URL = "/var-cms/login/"
LOGIN_REDIRECT_URL = "/var-cms/"
3. Add URL Routing
Include the var_cms routes in your project's main urls.py:
# urls.py
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... other paths
path("var-cms/", include("var_cms.urls", namespace="var_cms")),
]
# CRITICAL: Serve uploaded media files (images/files) during local development
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
🧪 Seeding the Demo App (Optional)
If you are developing or exploring features in the source repository:
- Run migrations to initialize the database:
python manage.py migrate
- Run the seed management command to generate default database models, pages, media, and test accounts:
python manage.py seed_demo
- Start the server:
python manage.py runserver
- Access the dashboard at
http://127.0.0.1:8000/var-cms/.
Demo User Accounts
| Username | Password | Role / Group | Permissions |
|---|---|---|---|
| admin | admin | superuser | Full unrestricted access |
| editor | editor | editor | Add + Edit (Cannot delete) |
| author | author | author | Add + Edit specific fields (Cannot delete) |
| viewer | viewer | viewer | List + View records only |
| alice | alice | viewer | Viewer permissions, with delete override |
🛠️ Registering Models (Example)
Create a file named var_cms_admin.py in any of your Django apps. It is automatically discovered on startup.
# myapp/var_cms_admin.py
from var_cms.registry import var_cms_site, VarCMSModelAdmin
from var_cms.permissions import RolePermission, UserPermission
from .models import Article
class ArticleAdmin(VarCMSModelAdmin):
list_display = ["title", "category", "author", "status", "created_at"]
list_filter = ["status", "category"]
search_fields = ["title", "body", "author"]
readonly_fields = ["created_at", "updated_at", "view_count"]
# Enable Quill.js Rich Text Editor on body field
html_fields = ["body"]
# Custom icon from Lucide
icon = "file-text"
# Regex validator: client-side + server-side validation
regex_validators = {
"slug": (r"^[a-z0-9-]+$", "Slug must consist of lowercase letters, numbers, and hyphens only.")
}
# Define role permissions
permissions = [
RolePermission("superuser", add=True, list=True, view=True, edit=True, delete=True),
RolePermission("editor", add=True, list=True, view=True, edit=True, delete=False),
RolePermission("author", add=True, list=True, view=True, edit=True, delete=False),
RolePermission("viewer", add=False, list=True, view=True, edit=False, delete=False),
UserPermission("alice", add=True, list=True, view=True, edit=True, delete=True),
]
# Limit editable fields by user role
role_editable_fields = {
"superuser": "__all__",
"editor": ["title", "slug", "body", "status", "category"],
"author": ["title", "body", "status"],
"*": [],
}
# Register the model on the custom site
var_cms_site.register(Article, ArticleAdmin)
📝 Custom Form Layouts & Field Settings
You can customize the column widths, widget styles, field placeholders, and help messages directly in your model's VarCMSModelAdmin registration:
form_field_widths: A dictionary mapping field names to layout width presets. The form runs on a 12-column grid and expands to fill the entire remaining width of the screen. Available width options:"full": Spans the full width of the form (12 columns). Checkboxes and Textareas take full-width by default."half": Spans half the width of the form (6 columns). All other standard fields default to half-width so that two fields sit side-by-side."one-third": Spans one-third of the form (4 columns)."two-thirds": Spans two-thirds of the form (8 columns)."one-fourth": Spans one-fourth of the form (3 columns)."three-fourths": Spans three-fourths of the form (9 columns).
form_field_classes: A dictionary mapping field names to container CSS classes.form_field_styles: A dictionary mapping field names to container custom inline CSS style rules.form_widget_classes: A dictionary mapping field names to CSS classes injected directly on the input/select/textarea widget itself.form_field_placeholders: A dictionary mapping field names to custom input placeholders.form_field_help_texts: A dictionary mapping field names to custom user help messages.
Width Preset Example
class ArticleAdmin(VarCMSModelAdmin):
# Form layout width settings (simple presets, no raw CSS needed)
form_field_widths = {
"title": "two-thirds",
"status": "one-third",
"category": "half",
"author": "half",
}
# Widget class injections (optional)
form_widget_classes = {
"title": "form-control-lg",
}
# Placeholders & custom instructions
form_field_placeholders = {
"title": "Enter article title...",
}
form_field_help_texts = {
"body": "Write the full article details using the Quill editor.",
}
Field Row Grouping (form_field_rows)
Group multiple fields into a single visual row using form_field_rows. Fields in the same row will automatically share the available width equally (e.g., 3 fields = 4 columns each on a 12-col grid).
- Fields listed in a row override any individual
form_field_widthsfor those fields. - Fields not included in any row continue to use the default width rules.
- Supports responsive wrapping on smaller screens automatically.
class CustomerAdmin(VarCMSModelAdmin):
# Show first_name, last_name side-by-side (2 cols = each gets 6)
# Show mobile, email, dob in one row (3 cols = each gets 4)
form_field_rows = [
["first_name", "last_name"],
["mobile", "email", "date_of_birth"],
]
Custom Dropdown Widget Types (form_field_widgets)
Control the dropdown experience for any ForeignKey, CharField with choices, or ManyToManyField using form_field_widgets.
Available widget types:
"select"— Standard HTML<select>dropdown (default behaviour, no override needed)."select_search"— A beautiful custom searchable dropdown with a live search input. No external dependency needed."multiselect"— Renders all choices as a styled checkbox list for multi-selection."multiselect_search"— Same as above but with a search/filter input above the list.
class OrderAdmin(VarCMSModelAdmin):
form_field_widgets = {
"status": "select", # default plain dropdown
"customer": "select_search", # searchable dropdown
"tags": "multiselect_search", # checkbox list with search
}
Note:
multiselectandmultiselect_searchwork best withManyToManyFieldfields. ForForeignKeyfields, useselect_searchinstead.
🎨 Layout Customizations
You can customize the accent color scheme using HSL values on the global var_cms_site registry:
# Custom accent color (Emerald green)
var_cms_site.accent_color = "142, 72%, 45%"
📁 URL Structure
/var-cms/ → Admin Dashboard
/var-cms/{app}/{model}/ → Paginated List view
/var-cms/{app}/{model}/add/ → Object Creation Form
/var-cms/{app}/{model}/{pk}/ → Object Modification Form
/var-cms/{app}/{model}/{pk}/view/ → Read-only Details view
/var-cms/{app}/{model}/{pk}/delete/→ Object Delete confirmation
/var-cms/api/media/crop/ → POST endpoint: crop image
/var-cms/api/media/convert/ → POST endpoint: convert media file type
📖 Detailed Integration & How To Use Guide
For detailed reference on branding customizations, optional two-factor authentication (OTP), and role-based permissions, see below:
🎨 Branding & Customization Settings
You can customize the header, subtitle, logo, HSL accent color, and email verification options directly in your Django settings.py:
# settings.py
VAR_CMS_SITE_HEADER = "VAR CMS" # Custom brand title
VAR_CMS_SITE_SUB = "ADMIN PANEL" # Subtitle
VAR_CMS_SITE_URL = "/" # "View Site" redirect URL
VAR_CMS_LOGO_URL = "/static/var_cms/var.png" # Brand Logo
VAR_CMS_ACCENT_COLOR = "142, 72%, 45%" # Custom HSL accent color (Emerald green)
VAR_CMS_ENABLE_OTP = False # Optional email OTP 2FA on login
# Optional Developer Profile (shown in Help section)
VAR_CMS_DEVELOPER_NAME = "Rahul Baberwal"
VAR_CMS_DEVELOPER_WEBSITE = "https://rahulbaberwal.com"
VAR_CMS_DEVELOPER_GITHUB = "https://github.com/rahul-baberwal"
VAR_CMS_DEVELOPER_LINKEDIN = "https://linkedin.com/in/rahul-baberwal"
VAR_CMS_DEVELOPER_EMAIL = "im@rahulbaberwal.com"
VAR_CMS_DEVELOPER_IMAGE = "https://github.com/rahul-baberwal.png"
📊 Dashboard Card Visibility & Action Buttons
You can customize whether specific model cards appear on the dashboard, and add custom navigation buttons and links directly within your model registration class.
1. Show or Hide Cards
By default, every registered model is hidden from the dashboard (dashboard_card = False by default). You can show or hide a card in the following ways:
- Locally on the ModelAdmin Class: Set
dashboard_card = Trueto show the card.class InvoiceAdmin(VarCMSModelAdmin): dashboard_card = True # will appear on dashboard class LogAdmin(VarCMSModelAdmin): dashboard_card = False # won't appear on dashboard (default)
- Globally in settings.py: Configure shown/hidden card settings:
# Hide specific cards: VAR_CMS_HIDDEN_DASHBOARD_CARDS = ["logentry", "demo.category"] # Show ONLY these cards: VAR_CMS_SHOWN_DASHBOARD_CARDS = ["invoice", "customer"] # show ONLY these
2. Adding Card Buttons & Links
You can specify custom quick-action buttons at the bottom of each dashboard card using the card_buttons attribute on VarCMSModelAdmin.
Each button is represented by a dictionary with:
label: The text displayed on the button.action: Built-in actions like"list"(navigates to the model's list view) or"add"(navigates to the add form).url(optional): Any custom relative or absolute URL. Used ifactionis not set.class(optional): Button style classes, e.g.,"btn-primary","btn-ghost","btn-danger".
class ArticleAdmin(VarCMSModelAdmin):
icon = "file-text"
card_buttons = [
{"label": "All Articles", "action": "list"},
{"label": "Write Draft", "action": "add"},
{"label": "External Link", "url": "https://example.com", "class": "btn-ghost"}
]
### ⚡ Custom Object Actions
You can add custom action buttons (like "Approve", "Send Notification", "Mark Active") to both the **List View** table rows and the **Details View** page.
To define custom object actions, define `custom_object_actions` on your `VarCMSModelAdmin` class. Each action is represented by a dictionary containing:
- `name`: Unique string identifier for the action (used in the URL).
- `label`: Display text on the button.
- `class` (optional): CSS class for styling, e.g., `"btn-primary"`, `"btn-green"`, `"btn-blue"`, `"btn-danger"`, or `"btn-ghost"`.
- `icon` (optional): Name of a Lucide icon (e.g., `"check-circle"`, `"mail"`, `"shield"`).
- `action_fn`: A callable or a string naming a method on the `VarCMSModelAdmin` class that executes the action logic. The function receives `(self, request, obj)`.
If the `action_fn` returns `None` (or doesn't return anything), the user will be automatically redirected back to the referring page. If you want custom routing, the function can return a custom `HttpResponse` (such as a redirect or JSON response).
#### Example 1: Approve Company (with logic checking)
In this use case, we want to check if a company has uploaded all required documents before approving it. If they are missing, we show an error message using Django's message framework.
```python
class CompanyAdmin(VarCMSModelAdmin):
list_display = ["name", "is_approved", "documents_uploaded"]
custom_object_actions = [
{
"name": "approve",
"label": "Approve",
"class": "btn-green",
"icon": "check-circle",
"action_fn": "approve_company"
}
]
def approve_company(self, request, obj):
from django.contrib import messages
# logic check
if not obj.documents_uploaded:
messages.error(request, f"Cannot approve {obj.name} - documents are not uploaded yet.")
return None # Redirect back with error
obj.is_approved = True
obj.save()
messages.success(request, f"Company {obj.name} has been successfully approved.")
return None
Example 2: Send welcome email to Subscriber
In this use case, we want a button to manually trigger a welcome email notification to a subscriber.
class SubscriberAdmin(VarCMSModelAdmin):
list_display = ["email", "first_name", "status"]
custom_object_actions = [
{
"name": "send_welcome",
"label": "Send Welcome",
"class": "btn-blue",
"icon": "mail",
"action_fn": "send_welcome_email"
}
]
def send_welcome_email(self, request, obj):
from django.core.mail import send_mail
from django.contrib import messages
try:
send_mail(
"Welcome to our newsletter!",
f"Hello {obj.first_name},\nThank you for joining us!",
"noreply@example.com",
[obj.email]
)
messages.success(request, f"Welcome email sent successfully to {obj.email}.")
except Exception as e:
messages.error(request, f"Failed to send email: {e}")
return None
### 🔑 Authentication & Password Tools
#### 1. Custom Glassmorphic Login
- A premium, modern dark login interface is provided out-of-the-box at `/var-cms/login/`.
#### 2. Optional OTP Verification (2FA)
- When `enable_otp = True`, successful user logins redirect to an OTP verification view.
- The system sends a 6-digit code to the user's email.
- **Development Tip**: If SMTP parameters are not configured in `settings.py`, the code prints directly to your terminal console as `[VAR CMS OTP]: ******` to prevent developers from getting locked out.
#### 3. Forgot Password Request
- Includes a "Forgot Password" link on the login screen. It prompts users to enter their email or username, generates a password reset OTP, and allows defining a new password securely.
#### 4. Logged-in Password Reset
- Users can change their password directly inside the dashboard. Click the **User profile badge** -> select **Reset Password**. It renders a custom password modification form embedded within the base CMS template.
---
## 📖 Complete Demo Reference Examples
Below are the complete source files from the demo application showcasing how models are declared and how they integrate with custom role-based permissions, Quill editors, image croppers, and validators in `django-var-cms`:
### 1. Model Definitions (`demo/models.py`)
```python
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
description = models.TextField(blank=True)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "category"
verbose_name_plural = "categories"
ordering = ["name"]
def __str__(self):
return self.name
STATUS_CHOICES = [("draft", "Draft"), ("published", "Published"), ("archived", "Archived")]
class Article(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
author = models.CharField(max_length=120)
body = models.TextField()
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="draft")
is_featured = models.BooleanField(default=False)
view_count = models.PositiveIntegerField(default=0)
rating = models.DecimalField(max_digits=3, decimal_places=1, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "article"
verbose_name_plural = "articles"
ordering = ["-created_at"]
def __str__(self):
return self.title
class MediaAsset(models.Model):
ASSET_TYPES = [("image", "Image"), ("video", "Video"), ("audio", "Audio"), ("document", "Document"), ("other", "Other")]
title = models.CharField(max_length=200)
asset_type = models.CharField(max_length=20, choices=ASSET_TYPES, default="image")
image = models.ImageField(upload_to="var_cms/images/%Y/%m/", blank=True, null=True)
file = models.FileField(upload_to="var_cms/files/%Y/%m/", blank=True, null=True)
alt_text = models.CharField(max_length=255, blank=True)
description = models.TextField(blank=True)
tags = models.CharField(max_length=300, blank=True, help_text="Comma-separated tags")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "media asset"
verbose_name_plural = "media assets"
def __str__(self):
return self.title
class Page(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
meta_desc = models.CharField(max_length=160, blank=True)
body = models.TextField()
parent = models.ForeignKey("self", null=True, blank=True, on_delete=models.SET_NULL, related_name="children")
is_published = models.BooleanField(default=False)
show_in_nav = models.BooleanField(default=True)
sort_order = models.PositiveSmallIntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "page"
verbose_name_plural = "pages"
ordering = ["sort_order", "title"]
def __str__(self):
return self.title
2. CMS Administration Configuration (demo/var_cms_admin.py)
from var_cms.registry import var_cms_site, VarCMSModelAdmin
from var_cms.permissions import RolePermission, UserPermission
from .models import Article, Category, MediaAsset, Page
# ── Custom CMS branding configurations ─────────────────────────────────────
var_cms_site.site_header = "CMS"
var_cms_site.site_sub = "CONTROL PANEL"
var_cms_site.site_url = "https://example.com"
var_cms_site.logo_url = "/static/var_cms/var.png"
var_cms_site.accent_color = "142, 72%, 45%" # Emerald green
var_cms_site.enable_otp = False
# ── Developer Profile configurations ─────────────────────────────────────────
var_cms_site.developer_name = "Rahul Baberwal"
var_cms_site.developer_website = "https://rahulbaberwal.com"
var_cms_site.developer_github = "https://github.com/rahul-baberwal"
var_cms_site.developer_linkedin = "https://linkedin.com/in/rahul-baberwal"
var_cms_site.developer_email = "im@rahulbaberwal.com"
var_cms_site.developer_image = "https://github.com/rahul-baberwal.png"
class CategoryAdmin(VarCMSModelAdmin):
list_display = ["name", "slug", "is_active", "created_at"]
list_filter = ["is_active"]
search_fields = ["name", "slug", "description"]
readonly_fields = ["created_at"]
ordering = ["name"]
icon = "folder"
regex_validators = {
"slug": (r"^[a-z0-9-]+$", "Slug must consist of lowercase letters, numbers, and hyphens only.")
}
permissions = [
RolePermission("superuser", add=True, list=True, view=True, edit=True, delete=True),
RolePermission("editor", add=True, list=True, view=True, edit=True, delete=False),
RolePermission("viewer", add=False, list=True, view=True, edit=False, delete=False),
]
role_editable_fields = {
"superuser": "__all__",
"editor": ["name", "description", "is_active"],
}
class ArticleAdmin(VarCMSModelAdmin):
list_display = ["title", "category", "author", "status", "is_featured", "view_count", "created_at"]
list_filter = ["status", "is_featured", "category"]
search_fields = ["title", "body", "author"]
readonly_fields = ["created_at", "updated_at", "view_count"]
ordering = ["-created_at"]
list_per_page = 20
html_fields = ["body"] # Quill editor
icon = "file-text"
card_buttons = [
{"label": "All Articles", "action": "list"},
{"label": "Write Draft", "action": "add"}
]
permissions = [
RolePermission("superuser", add=True, list=True, view=True, edit=True, delete=True),
RolePermission("editor", add=True, list=True, view=True, edit=True, delete=False),
RolePermission("author", add=True, list=True, view=True, edit=True, delete=False),
RolePermission("viewer", add=False, list=True, view=True, edit=False, delete=False),
UserPermission("alice", add=True, list=True, view=True, edit=True, delete=True),
]
role_editable_fields = {
"superuser": "__all__",
"editor": ["title", "slug", "body", "status", "category", "is_featured"],
"author": ["title", "body", "status"],
"*": [],
}
class MediaAssetAdmin(VarCMSModelAdmin):
list_display = ["title", "asset_type", "image", "file", "tags", "created_at"]
list_filter = ["asset_type"]
search_fields = ["title", "alt_text", "tags", "description"]
readonly_fields = ["created_at"]
icon = "image"
permissions = [
RolePermission("superuser", add=True, list=True, view=True, edit=True, delete=True),
RolePermission("editor", add=True, list=True, view=True, edit=True, delete=True),
RolePermission("viewer", add=False,list=True, view=True, edit=False,delete=False),
]
role_editable_fields = {
"superuser": "__all__",
"editor": "__all__",
}
class PageAdmin(VarCMSModelAdmin):
list_display = ["title", "slug", "parent", "is_published", "show_in_nav", "sort_order"]
list_filter = ["is_published", "show_in_nav"]
search_fields = ["title", "slug", "body", "meta_desc"]
readonly_fields = ["created_at"]
ordering = ["sort_order", "title"]
html_fields = ["body"]
icon = "book-open"
permissions = [
RolePermission("superuser", add=True, list=True, view=True, edit=True, delete=True),
RolePermission("editor", add=True, list=True, view=True, edit=True, delete=False),
RolePermission("viewer", add=False,list=True, view=True, edit=False,delete=False),
]
role_editable_fields = {
"superuser": "__all__",
"editor": ["title", "body", "meta_desc", "is_published", "show_in_nav", "sort_order"],
}
var_cms_site.register(Category, CategoryAdmin)
var_cms_site.register(Article, ArticleAdmin)
var_cms_site.register(MediaAsset, MediaAssetAdmin)
var_cms_site.register(Page, PageAdmin)
⚡ Tailwind CSS Integration
django-var-cms plays beautifully with Tailwind CSS projects. By installing the optional [tailwind] extra dependency:
pip install django-var-cms[tailwind]
This registers django-tailwind-cli in your project, allowing you to use utility-first styles for compiling layout templates, custom dashboards, or frontend theme assets using standard commands:
# Build production bundle
python manage.py tailwind build
# Start dev server with hot reload
python manage.py tailwind start
👥 Credits & Authors
Created and maintained by Rahul Baberwal — rahulbaberwal.com.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_var_cms-1.1.5.tar.gz.
File metadata
- Download URL: django_var_cms-1.1.5.tar.gz
- Upload date:
- Size: 777.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e63cff85831eaaf2c95921baeb253370d7791a40742ed593c7e203e97eb1aadd
|
|
| MD5 |
7c551582913518ca47c54ca3949aa34c
|
|
| BLAKE2b-256 |
2f851681f2951e647688ce4bdf91298ad5d10f02e15254dfacd24024ef044c89
|
Provenance
The following attestation bundles were made for django_var_cms-1.1.5.tar.gz:
Publisher:
publish.yml on rahul-baberwal/django-var-cms
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_var_cms-1.1.5.tar.gz -
Subject digest:
e63cff85831eaaf2c95921baeb253370d7791a40742ed593c7e203e97eb1aadd - Sigstore transparency entry: 1823386597
- Sigstore integration time:
-
Permalink:
rahul-baberwal/django-var-cms@e1a4bf3840868763f91efa5f51bf9b99db5f238b -
Branch / Tag:
refs/tags/v1.1.5 - Owner: https://github.com/rahul-baberwal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e1a4bf3840868763f91efa5f51bf9b99db5f238b -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_var_cms-1.1.5-py3-none-any.whl.
File metadata
- Download URL: django_var_cms-1.1.5-py3-none-any.whl
- Upload date:
- Size: 792.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98b0754697c12dc91b3235ae39a7a3293e1f52d5f84a2845f335529d30d890db
|
|
| MD5 |
cf7ec6480a2ef8dd6e024a2ba0260c22
|
|
| BLAKE2b-256 |
c519acab44402f5d299c9bd144b6666b99de41ce1eba45deefaed460ae216f7f
|
Provenance
The following attestation bundles were made for django_var_cms-1.1.5-py3-none-any.whl:
Publisher:
publish.yml on rahul-baberwal/django-var-cms
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_var_cms-1.1.5-py3-none-any.whl -
Subject digest:
98b0754697c12dc91b3235ae39a7a3293e1f52d5f84a2845f335529d30d890db - Sigstore transparency entry: 1823386620
- Sigstore integration time:
-
Permalink:
rahul-baberwal/django-var-cms@e1a4bf3840868763f91efa5f51bf9b99db5f238b -
Branch / Tag:
refs/tags/v1.1.5 - Owner: https://github.com/rahul-baberwal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e1a4bf3840868763f91efa5f51bf9b99db5f238b -
Trigger Event:
release
-
Statement type: