diff --git a/docs/configuration.md b/docs/configuration.md
index a224ea83..3566975a 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -289,9 +289,9 @@ Add a template for your model on your main template directory,
e.g [app/templates/admin/app_name/model_name/submit_line.html](https://github.com/farridav/django-jazzmin/tree/master/tests/test_app/library/books/templates/admin/loans/bookloan/submit_line.html)
```djangotemplate
-{# extends "admin/submit_line.html" #}
+{#% extends "admin/submit_line.html" %#}
-{% block extra-actions %}
+{#% block extra-actions %#}
{# For a simple link #}
-{% endblock %}
+{#% endblock %#}
```
If you are adding a button that needs processing with the form, e.g (Save and send) you will need to add the
diff --git a/jazzmin/settings.py b/jazzmin/settings.py
index b53d64ed..3b5084f7 100644
--- a/jazzmin/settings.py
+++ b/jazzmin/settings.py
@@ -30,6 +30,8 @@
############
# Links to put along the nav bar
"topmenu_links": [],
+ # Whether or not we use icons on the top menu
+ "topmenu_icons": False,
#############
# User Menu #
#############
diff --git a/jazzmin/templatetags/jazzmin.py b/jazzmin/templatetags/jazzmin.py
index c3fd872b..069581ed 100644
--- a/jazzmin/templatetags/jazzmin.py
+++ b/jazzmin/templatetags/jazzmin.py
@@ -31,7 +31,7 @@
get_admin_url,
make_menu,
has_fieldsets_check,
- regroup_available_apps,
+ regroup_apps,
)
User = get_user_model()
@@ -64,7 +64,7 @@ def get_side_menu(context: Context, using: str = "available_apps") -> List[Dict]
# If we are using custom grouping, overwrite available_apps based on our grouping
if options.get("custom_menu") and options["custom_menu"]:
- available_apps = regroup_available_apps(available_apps, options["custom_menu"])
+ available_apps = regroup_apps(available_apps, options["custom_menu"])
for app in available_apps:
app_label = app["app_label"].lower()
@@ -88,13 +88,18 @@ def get_side_menu(context: Context, using: str = "available_apps") -> List[Dict]
custom_link_names = [x.get("name", "").lower() for x in app_custom_links]
model_ordering = list(
- filter(lambda x: x.lower().startswith("{}.".format(app_label)) or x.lower() in custom_link_names, ordering,)
+ filter(
+ lambda x: x.lower().startswith("{}.".format(app_label)) or x.lower() in custom_link_names,
+ ordering,
+ )
)
if len(menu_items):
if model_ordering:
menu_items = order_with_respect_to(
- menu_items, model_ordering, getter=lambda x: x.get("model_str", x.get("name", "").lower()),
+ menu_items,
+ model_ordering,
+ getter=lambda x: x.get("model_str", x.get("name", "").lower()),
)
app["models"] = menu_items
menu.append(app)
@@ -420,7 +425,8 @@ def deleted(x: str) -> Dict:
elif "changed" in sub_message:
sub_message["changed"]["fields"] = get_text_list(
- [gettext(field_name) for field_name in sub_message["changed"]["fields"]], gettext("and"),
+ [gettext(field_name) for field_name in sub_message["changed"]["fields"]],
+ gettext("and"),
)
if "name" in sub_message["changed"]:
sub_message["changed"]["name"] = gettext(sub_message["changed"]["name"])
@@ -443,7 +449,7 @@ def style_bold_first_word(message: str) -> SafeText:
message_words = escape(message).split()
if not len(message_words):
- return ""
+ return mark_safe("")
message_words[0] = "{}".format(message_words[0])
diff --git a/jazzmin/utils.py b/jazzmin/utils.py
index 8eab3407..63159d84 100644
--- a/jazzmin/utils.py
+++ b/jazzmin/utils.py
@@ -1,12 +1,12 @@
import logging
-from typing import List, Union, Dict, Set, Callable
+from typing import List, Union, Dict, Set, Callable, Any
from urllib.parse import urlencode
from django.apps import apps
from django.contrib.admin import ListFilter
from django.contrib.admin.helpers import AdminForm
from django.contrib.auth.models import AbstractUser
-from django.db.models.base import ModelBase
+from django.db.models.base import ModelBase, Model
from django.db.models.options import Options
from django.utils.translation import gettext
@@ -33,16 +33,13 @@ def order_with_respect_to(original: List, reference: List, getter: Callable = la
return [y for x, y in sorted(zip(ranking, original), key=lambda x: x[0])]
-def get_admin_url(
- instance: Union[str, ModelBase], admin_site: str = "admin", from_app: bool = False, **kwargs: str
-) -> str:
+def get_admin_url(instance: Any, admin_site: str = "admin", from_app: bool = False, **kwargs: str) -> str:
"""
Return the admin URL for the given instance, model class or . string
"""
url = "#"
try:
-
if type(instance) == str:
app_label, model_name = instance.split(".")
model_name = model_name.lower()
@@ -150,16 +147,7 @@ def get_view_permissions(user: AbstractUser) -> Set[str]:
lower_perms = []
for perm in perms:
app, perm_codename = perm.split(".")
-<<<<<<< HEAD
lower_perms.append("{app}.{perm_codename}".format(app=app, perm_codename=perm_codename.lower()))
-=======
- lower_perms.append(
- "{app}.{perm_codename}".format(
- app=app,
- perm_codename=perm_codename.lower(),
- )
- )
->>>>>>> 3ec6d11 (test)
return {x.replace("view_", "") for x in lower_perms if "view" in x or "change" in x}
@@ -176,12 +164,7 @@ def make_menu(
menu = []
for link in links:
-
- perm_matches = []
- for perm in link.get("permissions", []):
- perm_matches.append(user.has_perm(perm))
-
- if not all(perm_matches):
+ if not all([user.has_perm(perm) for perm in link.get("permissions", [])]):
continue
# Url links
@@ -217,16 +200,7 @@ def make_menu(
# App links
elif "app" in link and allow_appmenus:
children = [
-<<<<<<< HEAD
{"name": child.get("verbose_name", child["name"]), "url": child["url"], "children": None}
-=======
- {
- "name": child.get("verbose_name", child["name"]),
- "url": child["url"],
- "children": None,
- "icon": options["icons"].get(child["model"].lower()),
- }
->>>>>>> 3ec6d11 (test)
for child in get_app_admin_urls(link["app"], admin_site=admin_site)
if child["model"] in model_permissions
]
@@ -252,7 +226,7 @@ def has_fieldsets_check(adminform: AdminForm) -> bool:
return True
-def regroup_available_apps(available_apps: List[Dict], grouping: Dict[str, List[str]]) -> List[Dict]:
+def regroup_apps(available_apps: List[Dict], grouping: Dict[str, List[str]]) -> List[Dict]:
# Make a list of all apps, and all models, keyed on app name or model name
all_models, all_apps = {}, {}
for app in available_apps:
diff --git a/tests/test_app/library/settings.py b/tests/test_app/library/settings.py
index d046500f..a6a98cef 100644
--- a/tests/test_app/library/settings.py
+++ b/tests/test_app/library/settings.py
@@ -71,15 +71,25 @@
DATABASES = {
"default": dj_database_url.config(
- env="DATABASE_URL", conn_max_age=500, default="sqlite:///{}".format(os.path.join(BASE_DIR, "db.sqlite3")),
+ env="DATABASE_URL",
+ conn_max_age=500,
+ default="sqlite:///{}".format(os.path.join(BASE_DIR, "db.sqlite3")),
)
}
AUTH_PASSWORD_VALIDATORS = [
- {"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",},
- {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",},
- {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",},
- {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",},
+ {
+ "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
+ },
+ {
+ "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
+ },
+ {
+ "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
+ },
+ {
+ "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
+ },
]
LANGUAGE_CODE = "en"
@@ -146,6 +156,7 @@
{"app": "books"},
{"app": "loans"},
],
+ # Whether or not we use icons on the top menu
"topmenu_icons": True,
#############
# User Menu #
@@ -179,7 +190,7 @@
}
]
},
- # Dont generate a menu based off installed apps, instead, craft one using this app/arbitrary name -> model mapping
+ # Dont generate a side menu from installed apps, instead, craft one using this app/arbitrary name -> model mapping
"custom_menu": {},
# Custom icons for side menu apps/models See https://fontawesome.com/icons?d=gallery&m=free
# for a list of icon classes