Files
Touchh/.venv/lib/python3.10/site-packages/jazzmin/settings.py
2024-12-06 10:45:08 +09:00

337 lines
13 KiB
Python

import copy
import logging
from typing import Any, Dict
from django.conf import settings
from django.templatetags.static import static
from .utils import get_admin_url, get_model_meta
logger = logging.getLogger(__name__)
DEFAULT_SETTINGS: Dict[str, Any] = {
# title of the window (Will default to current_admin_site.site_title)
"site_title": None,
# Title on the login screen (19 chars max) (will default to current_admin_site.site_header)
"site_header": None,
# Title on the brand (19 chars max) (will default to current_admin_site.site_header)
"site_brand": None,
# Relative path to logo for your site, used for brand on top left (must be present in static files)
"site_logo": "vendor/adminlte/img/AdminLTELogo.png",
# Relative path to logo for your site, used for login logo (must be present in static files. Defaults to site_logo)
"login_logo": None,
# Logo to use for login form in dark themes (must be present in static files. Defaults to login_logo)
"login_logo_dark": None,
# CSS classes that are applied to the logo
"site_logo_classes": "img-circle",
# Relative path to a favicon for your site, will default to site_logo if absent (ideally 32x32 px)
"site_icon": None,
# Welcome text on the login screen
"welcome_sign": "Welcome",
# Copyright on the footer
"copyright": "",
# The model admin to search from the search bar, search bar omitted if excluded
"search_model": None,
# Field name on user model that contains avatar ImageField/URLField/Charfield or a callable that receives the user
"user_avatar": None,
############
# Top Menu #
############
# Links to put along the nav bar
"topmenu_links": [],
#############
# User Menu #
#############
# Additional links to include in the user menu on the top right ('app' url type is not allowed)
"usermenu_links": [],
#############
# Side Menu #
#############
# Whether to display the side menu
"show_sidebar": True,
# Whether to aut expand the menu
"navigation_expanded": True,
# Hide these apps when generating side menu e.g (auth)
"hide_apps": [],
# Hide these models when generating side menu (e.g auth.user)
"hide_models": [],
# List of apps to base side menu ordering off of
"order_with_respect_to": [],
# Custom links to append to side menu app groups, keyed on app name
"custom_links": {},
# Custom icons for side menu apps/models See the link below
# https://fontawesome.com/icons?d=gallery&m=free&v=5.0.0,5.0.1,5.0.10,5.0.11,5.0.12,5.0.13,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.1.0,
# 5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2,5.13.0,5.12.0,
# 5.11.2,5.11.1,5.10.0,5.9.0,5.8.2,5.8.1,5.7.2,5.7.1,5.7.0,5.6.3,5.5.0,5.4.2
# for the full list of 5.13.0 free icon classes
"icons": {"auth": "fas fa-users-cog", "auth.user": "fas fa-user", "auth.Group": "fas fa-users"},
# Icons that are used when one is not manually specified
"default_icon_parents": "fas fa-chevron-circle-right",
"default_icon_children": "fas fa-circle",
#################
# Related Modal #
#################
# Activate Bootstrap modal
"related_modal_active": False,
#############
# UI Tweaks #
#############
# Relative paths to custom CSS/JS scripts (must be present in static files)
"custom_css": None,
"custom_js": None,
# Whether to link font from fonts.googleapis.com (use custom_css to supply font otherwise)
"use_google_fonts_cdn": True,
# Whether to show the UI customizer on the sidebar
"show_ui_builder": False,
###############
# Change view #
###############
# Render out the change view as a single form, or in tabs, current options are
# - single
# - horizontal_tabs (default)
# - vertical_tabs
# - collapsible
# - carousel
"changeform_format": "horizontal_tabs",
# override change forms on a per modeladmin basis
"changeform_format_overrides": {},
# Add a language dropdown into the admin
"language_chooser": False,
}
#######################################
# Currently available UI tweaks #
# Use the UI builder to generate this #
#######################################
DEFAULT_UI_TWEAKS: Dict[str, Any] = {
# Small text on the top navbar
"navbar_small_text": False,
# Small text on the footer
"footer_small_text": False,
# Small text everywhere
"body_small_text": False,
# Small text on the brand/logo
"brand_small_text": False,
# brand/logo background colour
"brand_colour": False,
# Link colour
"accent": "accent-primary",
# topmenu colour
"navbar": "navbar-white navbar-light",
# topmenu border
"no_navbar_border": False,
# Make the top navbar sticky, keeping it in view as you scroll
"navbar_fixed": False,
# Whether to constrain the page to a box (leaving big margins at the side)
"layout_boxed": False,
# Make the footer sticky, keeping it in view all the time
"footer_fixed": False,
# Make the sidebar sticky, keeping it in view as you scroll
"sidebar_fixed": False,
# sidemenu colour
"sidebar": "sidebar-dark-primary",
# sidemenu small text
"sidebar_nav_small_text": False,
# Disable expanding on hover of collapsed sidebar
"sidebar_disable_expand": False,
# Indent child menu items on sidebar
"sidebar_nav_child_indent": False,
# Use a compact sidebar
"sidebar_nav_compact_style": False,
# Use the AdminLTE2 style sidebar
"sidebar_nav_legacy_style": False,
# Use a flat style sidebar
"sidebar_nav_flat_style": False,
# Bootstrap theme to use (default, or from bootswatch, see THEMES below)
"theme": "default",
# Theme to use instead if the user has opted for dark mode (e.g darkly/cyborg/slate/solar/superhero)
"dark_mode_theme": None,
# The classes/styles to use with buttons
"button_classes": {
"primary": "btn-primary",
"secondary": "btn-secondary",
"info": "btn-info",
"warning": "btn-warning",
"danger": "btn-danger",
"success": "btn-success",
},
}
THEMES = {
# light themes
"default": "vendor/bootswatch/default/bootstrap.min.css",
"cerulean": "vendor/bootswatch/cerulean/bootstrap.min.css",
"cosmo": "vendor/bootswatch/cosmo/bootstrap.min.css",
"flatly": "vendor/bootswatch/flatly/bootstrap.min.css",
"journal": "vendor/bootswatch/journal/bootstrap.min.css",
"litera": "vendor/bootswatch/litera/bootstrap.min.css",
"lumen": "vendor/bootswatch/lumen/bootstrap.min.css",
"lux": "vendor/bootswatch/lux/bootstrap.min.css",
"materia": "vendor/bootswatch/materia/bootstrap.min.css",
"minty": "vendor/bootswatch/minty/bootstrap.min.css",
"pulse": "vendor/bootswatch/pulse/bootstrap.min.css",
"sandstone": "vendor/bootswatch/sandstone/bootstrap.min.css",
"simplex": "vendor/bootswatch/simplex/bootstrap.min.css",
"sketchy": "vendor/bootswatch/sketchy/bootstrap.min.css",
"spacelab": "vendor/bootswatch/spacelab/bootstrap.min.css",
"united": "vendor/bootswatch/united/bootstrap.min.css",
"yeti": "vendor/bootswatch/yeti/bootstrap.min.css",
# dark themes
"darkly": "vendor/bootswatch/darkly/bootstrap.min.css",
"cyborg": "vendor/bootswatch/cyborg/bootstrap.min.css",
"slate": "vendor/bootswatch/slate/bootstrap.min.css",
"solar": "vendor/bootswatch/solar/bootstrap.min.css",
"superhero": "vendor/bootswatch/superhero/bootstrap.min.css",
}
DARK_THEMES = ("darkly", "cyborg", "slate", "solar", "superhero")
CHANGEFORM_TEMPLATES = {
"single": "jazzmin/includes/single.html",
"carousel": "jazzmin/includes/carousel.html",
"collapsible": "jazzmin/includes/collapsible.html",
"horizontal_tabs": "jazzmin/includes/horizontal_tabs.html",
"vertical_tabs": "jazzmin/includes/vertical_tabs.html",
}
def get_search_model_string(search_model: str) -> str:
"""
Get a search model string for reversing an admin url.
Ensure the model name is lower cased but remain the app name untouched.
"""
app, model_name = search_model.split(".")
return "{app}.{model_name}".format(app=app, model_name=model_name.lower())
def get_settings() -> Dict:
jazzmin_settings = copy.deepcopy(DEFAULT_SETTINGS)
user_settings = {x: y for x, y in getattr(settings, "JAZZMIN_SETTINGS", {}).items() if y is not None}
jazzmin_settings.update(user_settings)
# Extract search model configuration from search_model setting
if jazzmin_settings["search_model"]:
if not isinstance(jazzmin_settings["search_model"], list):
jazzmin_settings["search_model"] = [jazzmin_settings["search_model"]]
jazzmin_settings["search_models_parsed"] = []
for search_model in jazzmin_settings["search_model"]:
jazzmin_search_model = {}
jazzmin_search_model["search_url"] = get_admin_url(get_search_model_string(search_model))
model_meta = get_model_meta(search_model)
if model_meta:
jazzmin_search_model["search_name"] = model_meta.verbose_name_plural.title()
else:
jazzmin_search_model["search_name"] = search_model.split(".")[-1] + "s"
jazzmin_settings["search_models_parsed"].append(jazzmin_search_model)
# Deal with single strings in hide_apps/hide_models and make sure we lower case 'em
if isinstance(jazzmin_settings["hide_apps"], str):
jazzmin_settings["hide_apps"] = [jazzmin_settings["hide_apps"]]
jazzmin_settings["hide_apps"] = [x.lower() for x in jazzmin_settings["hide_apps"]]
if isinstance(jazzmin_settings["hide_models"], str):
jazzmin_settings["hide_models"] = [jazzmin_settings["hide_models"]]
jazzmin_settings["hide_models"] = [x.lower() for x in jazzmin_settings["hide_models"]]
# Ensure icon model names and classes are lower case
jazzmin_settings["icons"] = {x.lower(): y.lower() for x, y in jazzmin_settings.get("icons", {}).items()}
# Default the site icon using the site logo
jazzmin_settings["site_icon"] = jazzmin_settings["site_icon"] or jazzmin_settings["site_logo"]
# Default the login logo using the site logo
jazzmin_settings["login_logo"] = jazzmin_settings["login_logo"] or jazzmin_settings["site_logo"]
# Default the login logo dark using the login logo
jazzmin_settings["login_logo_dark"] = jazzmin_settings["login_logo_dark"] or jazzmin_settings["login_logo"]
# ensure all model names are lower cased
jazzmin_settings["changeform_format_overrides"] = {
x.lower(): y.lower() for x, y in jazzmin_settings.get("changeform_format_overrides", {}).items()
}
return jazzmin_settings
def get_ui_tweaks() -> Dict:
raw_tweaks = copy.deepcopy(DEFAULT_UI_TWEAKS)
raw_tweaks.update(getattr(settings, "JAZZMIN_UI_TWEAKS", {}))
tweaks = {x: y for x, y in raw_tweaks.items() if y not in (None, "", False)}
# These options dont work well together
if tweaks.get("layout_boxed"):
tweaks.pop("navbar_fixed", None)
tweaks.pop("footer_fixed", None)
bool_map = {
"navbar_small_text": "text-sm",
"footer_small_text": "text-sm",
"body_small_text": "text-sm",
"brand_small_text": "text-sm",
"sidebar_nav_small_text": "text-sm",
"no_navbar_border": "border-bottom-0",
"sidebar_disable_expand": "sidebar-no-expand",
"sidebar_nav_child_indent": "nav-child-indent",
"sidebar_nav_compact_style": "nav-compact",
"sidebar_nav_legacy_style": "nav-legacy",
"sidebar_nav_flat_style": "nav-flat",
"layout_boxed": "layout-boxed",
"sidebar_fixed": "layout-fixed",
"navbar_fixed": "layout-navbar-fixed",
"footer_fixed": "layout-footer-fixed",
"actions_sticky_top": "sticky-top",
}
for key, value in bool_map.items():
if key in tweaks:
tweaks[key] = value
def classes(*args: str) -> str:
return " ".join([tweaks.get(arg, "") for arg in args]).strip()
theme = tweaks["theme"]
if theme not in THEMES:
logger.warning("{} not found in {}, using default".format(theme, THEMES.keys()))
theme = "default"
dark_mode_theme = tweaks.get("dark_mode_theme", None)
if dark_mode_theme and dark_mode_theme not in DARK_THEMES:
logger.warning("{} is not a dark theme, using darkly".format(dark_mode_theme))
dark_mode_theme = "darkly"
theme_body_classes = " theme-{}".format(theme)
if theme in DARK_THEMES:
theme_body_classes += " dark-mode"
ret = {
"raw": raw_tweaks,
"theme": {"name": theme, "src": static(THEMES[theme])},
"sidebar_classes": classes("sidebar", "sidebar_disable_expand"),
"navbar_classes": classes("navbar", "no_navbar_border", "navbar_small_text"),
"body_classes": classes(
"accent", "body_small_text", "navbar_fixed", "footer_fixed", "sidebar_fixed", "layout_boxed"
)
+ theme_body_classes,
"actions_classes": classes("actions_sticky_top"),
"sidebar_list_classes": classes(
"sidebar_nav_small_text",
"sidebar_nav_flat_style",
"sidebar_nav_legacy_style",
"sidebar_nav_child_indent",
"sidebar_nav_compact_style",
),
"brand_classes": classes("brand_small_text", "brand_colour"),
"footer_classes": classes("footer_small_text"),
"button_classes": tweaks["button_classes"],
}
if dark_mode_theme:
ret["dark_mode_theme"] = {"name": dark_mode_theme, "src": static(THEMES[dark_mode_theme])}
return ret