Skip to content
This repository was archived by the owner on Aug 20, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c23ce1b
copied autocomplete.py from django/django/contrib/admin/views
khanxmetu Mar 28, 2025
20fee32
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 28, 2025
3bcedbe
Write JSON view based on AutocompleteJsonView
khanxmetu Mar 28, 2025
e4461f0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 28, 2025
fd4870d
Create custom AdminSite, and override default admin site with it
khanxmetu Mar 28, 2025
8b1ff60
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 28, 2025
e9b03d4
Add the new site-wide view to urlpatterns of the custom AdminSite
khanxmetu Mar 28, 2025
bc75e1b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 28, 2025
bba8647
fix: ensure queryset ordering for deterministic results and avoid Uno…
khanxmetu Mar 28, 2025
661d348
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 28, 2025
bdc5905
style: fix formatting issues from ruff
khanxmetu Mar 29, 2025
23b1b8d
fix: override default admin site by replacing underlying AdminSite
khanxmetu Mar 29, 2025
ad1201b
add objects admin change url to instance search response
khanxmetu Mar 30, 2025
fe90ac6
frontend for instance search based on select2
khanxmetu Mar 30, 2025
48bb7a9
fix: f-string concatenation
khanxmetu Mar 30, 2025
5bed070
fix: selectbox config options
khanxmetu Mar 30, 2025
211c1ae
fix: SelectBoxUtils should be assigned on ready
khanxmetu Mar 30, 2025
ca88e90
fix: clear selection on dialog close
khanxmetu Mar 30, 2025
433648b
override default admin site using AdminConfig
khanxmetu Apr 3, 2025
d37a1e8
use available_apps from context instead of all_apps template tag
khanxmetu Apr 3, 2025
0a755b2
fix darkmode with django autocomplete select2 css; wrap selectboxes i…
khanxmetu Apr 3, 2025
e3d9698
prepare for tests; allow selenium test runs from runtests script
khanxmetu Apr 3, 2025
432dcde
instance search tests
khanxmetu Apr 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ Then clone this repo somewhere and install it in editable mode with pip, e.g.
pip install -e ../django-admin-keyboard-shortcuts


Then add `django_admin_keyboard_shortcuts` to your `INSTALLED_APPS`. It must go
above the `django.contrib.admin` app so that the template overrides work.
You would need to replace `django.contrib.admin` with `django_admin_keyboard_shortcuts.apps.KSAdminConfig` in your `INSTALLED_APPS` to override the default admin site. See the `Django docs on overriding the default admin site <https://docs.djangoproject.com/en/5.1/ref/contrib/admin/#overriding-the-default-admin-site>`_. Then add `django_admin_keyboard_shortcuts.apps.AdminKeyboardShortcutsConfig`. It must go
above the `django_admin_keyboard_shortcuts.apps.KSAdminConfig` app so that the template overrides work.

Now you can hack away.

Expand Down
5 changes: 5 additions & 0 deletions django_admin_keyboard_shortcuts/apps.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
from django.apps import AppConfig
from django.contrib.admin.apps import AdminConfig


class AdminKeyboardShortcutsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "django_admin_keyboard_shortcuts"
label = "admin_keyboard_shortcuts"


class KSAdminConfig(AdminConfig):
default_site = "django_admin_keyboard_shortcuts.sites.KSAdminSite"
35 changes: 35 additions & 0 deletions django_admin_keyboard_shortcuts/sites.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from functools import update_wrapper

from django.contrib import admin
from django.urls import path
from django.urls import reverse_lazy

from django_admin_keyboard_shortcuts.views.instance_search import InstanceSearchJsonView


# If/when this gets merged into django,
# the contents of this class should be merged into django/contrib/admin/sites.AdminSite
# Snippets based on autocomplete_view logic in django/contrib/admin/sites.py
class KSAdminSite(admin.AdminSite):
def get_urls(self):
def wrap(view, cacheable=False):
def wrapper(*args, **kwargs):
return self.admin_view(view, cacheable)(*args, **kwargs)

wrapper.admin_site = self
# Used by LoginRequiredMiddleware.
wrapper.login_url = reverse_lazy("admin:login", current_app=self.name)
return update_wrapper(wrapper, view)

urls = super().get_urls()
custom_urls = [
path(
"instance_search/",
wrap(self.instance_search_view),
name="instance_search",
),
]
return custom_urls + urls

def instance_search_view(self, request):
return InstanceSearchJsonView.as_view(admin_site=self)(request)
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import url('shortcuts_select.css');

kbd {
background-color: var(--body-bg);
border-radius: 3px;
Expand Down Expand Up @@ -55,7 +57,7 @@ dialog ul {
padding: 0;
}

dialog ul li {
dialog:not(#instance-list-dialog) ul li {
align-items: center;
column-gap: 1em;
display: flex;
Expand Down
284 changes: 284 additions & 0 deletions django_admin_keyboard_shortcuts/static/admin/css/shortcuts_select.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
/*
modified from django/contrib/admin/static/admin/css/autocomplete.css
to work with data-theme=shortcuts-select
*/

select.shortcuts-select {
width: 20em;
}

.select2-container--shortcuts-select.select2-container {
min-height: 30px;
}

.select2-container--shortcuts-select .select2-selection--single,
.select2-container--shortcuts-select .select2-selection--multiple {
min-height: 30px;
padding: 0;
}

.select2-container--shortcuts-select.select2-container--focus .select2-selection,
.select2-container--shortcuts-select.select2-container--open .select2-selection {
border-color: var(--body-quiet-color);
min-height: 30px;
}

.select2-container--shortcuts-select.select2-container--focus .select2-selection.select2-selection--single,
.select2-container--shortcuts-select.select2-container--open .select2-selection.select2-selection--single {
padding: 0;
}

.select2-container--shortcuts-select.select2-container--focus .select2-selection.select2-selection--multiple,
.select2-container--shortcuts-select.select2-container--open .select2-selection.select2-selection--multiple {
padding: 0;
}

.select2-container--shortcuts-select .select2-selection--single {
background-color: var(--body-bg);
border: 1px solid var(--border-color);
border-radius: 4px;
}

.select2-container--shortcuts-select .select2-selection--single .select2-selection__rendered {
color: var(--body-fg);
line-height: 30px;
}

.select2-container--shortcuts-select .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
}

.select2-container--shortcuts-select .select2-selection--single .select2-selection__placeholder {
color: var(--body-quiet-color);
}

.select2-container--shortcuts-select .select2-selection--single .select2-selection__arrow {
height: 26px;
position: absolute;
top: 1px;
right: 1px;
width: 20px;
}

.select2-container--shortcuts-select .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
left: 50%;
margin-left: -4px;
margin-top: -2px;
position: absolute;
top: 50%;
width: 0;
}

.select2-container--shortcuts-select[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left;
}

.select2-container--shortcuts-select[dir="rtl"] .select2-selection--single .select2-selection__arrow {
left: 1px;
right: auto;
}

.select2-container--shortcuts-select.select2-container--disabled .select2-selection--single {
background-color: var(--darkened-bg);
cursor: default;
}

.select2-container--shortcuts-select.select2-container--disabled .select2-selection--single .select2-selection__clear {
display: none;
}

.select2-container--shortcuts-select.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px;
}

.select2-container--shortcuts-select .select2-selection--multiple {
background-color: var(--body-bg);
border: 1px solid var(--border-color);
border-radius: 4px;
cursor: text;
}

.select2-container--shortcuts-select .select2-selection--multiple .select2-selection__rendered {
box-sizing: border-box;
list-style: none;
margin: 0;
padding: 0 10px 5px 5px;
width: 100%;
display: flex;
flex-wrap: wrap;
}

.select2-container--shortcuts-select .select2-selection--multiple .select2-selection__rendered li {
list-style: none;
}

.select2-container--shortcuts-select .select2-selection--multiple .select2-selection__placeholder {
color: var(--body-quiet-color);
margin-top: 5px;
float: left;
}

.select2-container--shortcuts-select .select2-selection--multiple .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin: 5px;
position: absolute;
right: 0;
}

.select2-container--shortcuts-select .select2-selection--multiple .select2-selection__choice {
background-color: var(--darkened-bg);
border: 1px solid var(--border-color);
border-radius: 4px;
cursor: default;
float: left;
margin-right: 5px;
margin-top: 5px;
padding: 0 5px;
}

.select2-container--shortcuts-select .select2-selection--multiple .select2-selection__choice__remove {
color: var(--body-quiet-color);
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 2px;
}

.select2-container--shortcuts-select .select2-selection--multiple .select2-selection__choice__remove:hover {
color: var(--body-fg);
}

.select2-container--shortcuts-select[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--shortcuts-select[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--shortcuts-select[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right;
}

.select2-container--shortcuts-select[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 5px;
margin-right: auto;
}

.select2-container--shortcuts-select[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto;
}

.select2-container--shortcuts-select.select2-container--focus .select2-selection--multiple {
border: solid var(--body-quiet-color) 1px;
outline: 0;
}

.select2-container--shortcuts-select.select2-container--disabled .select2-selection--multiple {
background-color: var(--darkened-bg);
cursor: default;
}

.select2-container--shortcuts-select.select2-container--disabled .select2-selection__choice__remove {
display: none;
}

.select2-container--shortcuts-select.select2-container--open.select2-container--above .select2-selection--single, .select2-container--shortcuts-select.select2-container--open.select2-container--above .select2-selection--multiple {
border-top-left-radius: 0;
border-top-right-radius: 0;
}

.select2-container--shortcuts-select.select2-container--open.select2-container--below .select2-selection--single, .select2-container--shortcuts-select.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}

.select2-container--shortcuts-select .select2-search--dropdown {
background: var(--darkened-bg);
}

.select2-container--shortcuts-select .select2-search--dropdown .select2-search__field {
background: var(--body-bg);
color: var(--body-fg);
border: 1px solid var(--border-color);
border-radius: 4px;
}

.select2-container--shortcuts-select .select2-search--inline .select2-search__field {
background: transparent;
color: var(--body-fg);
border: none;
outline: 0;
box-shadow: none;
-webkit-appearance: textfield;
}

.select2-container--shortcuts-select .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto;
color: var(--body-fg);
background: var(--body-bg);
}

.select2-container--shortcuts-select .select2-results__option[role=group] {
padding: 0;
}

.select2-container--shortcuts-select .select2-results__option[aria-disabled=true] {
color: var(--body-quiet-color);
}

.select2-container--shortcuts-select .select2-results__option[aria-selected=true] {
background-color: var(--selected-bg);
color: var(--body-fg);
}

.select2-container--shortcuts-select .select2-results__option .select2-results__option {
padding-left: 1em;
}

.select2-container--shortcuts-select .select2-results__option .select2-results__option .select2-results__group {
padding-left: 0;
}

.select2-container--shortcuts-select .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1em;
padding-left: 2em;
}

.select2-container--shortcuts-select .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -2em;
padding-left: 3em;
}

.select2-container--shortcuts-select .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -3em;
padding-left: 4em;
}

.select2-container--shortcuts-select .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -4em;
padding-left: 5em;
}

.select2-container--shortcuts-select .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -5em;
padding-left: 6em;
}

.select2-container--shortcuts-select .select2-results__option--highlighted[aria-selected] {
background-color: var(--primary);
color: var(--primary-fg);
}

.select2-container--shortcuts-select .select2-results__group {
cursor: default;
display: block;
padding: 6px;
}

.errors .select2-selection {
border: 1px solid var(--error-fg);
}
Loading
Loading