Features: 1) Remove AutocompleteFieldListFilter and related admin filters and templates; 2) Remove associated JavaScript, CSS, and Python logic; 3) Simplify admin configurations by dropping unused autocomplete filters;
Fixes: None; Extra: 1) Cleanup unused imports and redundant UI files; 2) Minor adjustments to filter handling in `core/admin.py`.
This commit is contained in:
parent
8a07fc69b1
commit
ce53eec560
5 changed files with 1 additions and 253 deletions
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
from contextlib import suppress
|
||||
|
||||
from constance.admin import Config
|
||||
|
|
@ -12,7 +11,6 @@ from modeltranslation.translator import NotRegistered, translator
|
|||
from modeltranslation.utils import get_translation_fields
|
||||
from mptt.admin import DraggableMPTTAdmin
|
||||
|
||||
from core.filters import AutocompleteFieldListFilter
|
||||
from core.forms import OrderForm, OrderProductForm, VendorForm
|
||||
from core.models import (
|
||||
Address,
|
||||
|
|
@ -249,8 +247,6 @@ class ProductAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin):
|
|||
"stocks__vendor",
|
||||
"created",
|
||||
"modified",
|
||||
("brand", AutocompleteFieldListFilter),
|
||||
("category", AutocompleteFieldListFilter),
|
||||
)
|
||||
search_fields = (
|
||||
"name",
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import json
|
|||
import logging
|
||||
import uuid
|
||||
|
||||
from django.contrib.admin import FieldListFilter
|
||||
from django.core.exceptions import BadRequest, ValidationError
|
||||
from django.core.exceptions import BadRequest
|
||||
from django.db.models import (
|
||||
Avg,
|
||||
Case,
|
||||
|
|
@ -17,7 +16,6 @@ from django.db.models import (
|
|||
When,
|
||||
)
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.forms import Media
|
||||
from django.utils.http import urlsafe_base64_decode
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_filters import (
|
||||
|
|
@ -505,78 +503,3 @@ class AddressFilter(FilterSet):
|
|||
class Meta:
|
||||
model = Address
|
||||
fields = ["uuid", "user_uuid", "user_email", "order_by"]
|
||||
|
||||
|
||||
class AutocompleteFieldListFilter(FieldListFilter):
|
||||
|
||||
template = "admin/autocomplete_filter.html"
|
||||
|
||||
def __init__(self, field, request, params, model, model_admin, field_path):
|
||||
self.lookup_kwarg = f"{field_path}__exact"
|
||||
self.lookup_val = request.GET.get(self.lookup_kwarg)
|
||||
self.field = field
|
||||
self.field_path = field_path
|
||||
self.model = model
|
||||
self.related_model = field.related_model
|
||||
super().__init__(field, request, params, model, model_admin, field_path)
|
||||
|
||||
def has_output(self):
|
||||
return True
|
||||
|
||||
def choices(self, changelist):
|
||||
choices = []
|
||||
if self.lookup_val:
|
||||
try:
|
||||
obj = self.related_model.objects.get(pk=self.lookup_val)
|
||||
choices.append(
|
||||
{
|
||||
"selected": True,
|
||||
"query_string": changelist.get_query_string(remove=[self.lookup_kwarg]),
|
||||
"display": str(obj),
|
||||
"value": obj.pk,
|
||||
}
|
||||
)
|
||||
except (self.related_model.DoesNotExist, ValidationError):
|
||||
pass
|
||||
return choices
|
||||
|
||||
def queryset(self, request, queryset):
|
||||
if self.lookup_val:
|
||||
try:
|
||||
return queryset.filter(**{self.lookup_kwarg: self.lookup_val})
|
||||
except (ValueError, ValidationError):
|
||||
pass
|
||||
return queryset
|
||||
|
||||
def expected_parameters(self):
|
||||
return [self.lookup_kwarg]
|
||||
|
||||
@property
|
||||
def media(self):
|
||||
extra = "" if self.used_parameters else ".min"
|
||||
js = [
|
||||
f"admin/js/vendor/jquery/jquery{extra}.js",
|
||||
f"admin/js/vendor/select2/select2.full{extra}.js",
|
||||
"admin/js/autocomplete_filter.js",
|
||||
]
|
||||
css = {
|
||||
"screen": [
|
||||
f"admin/css/vendor/select2/select2{extra}.css",
|
||||
"admin/css/autocomplete_filter.css",
|
||||
]
|
||||
}
|
||||
return Media(js=js, css=css)
|
||||
|
||||
def get_context_data(self):
|
||||
field_name = self.field_path.replace("__", "_")
|
||||
related_url = f'/admin/{self.related_model._meta.app_label}/{self.related_model._meta.model_name}/autocomplete/'
|
||||
|
||||
return {
|
||||
'field_name': field_name,
|
||||
'lookup_kwarg': self.lookup_kwarg,
|
||||
'lookup_val': self.lookup_val or '',
|
||||
'related_url': related_url,
|
||||
'placeholder': _('Search %s...') % self.related_model._meta.verbose_name,
|
||||
'clear_text': _('Clear'),
|
||||
'field_verbose_name': self.field.verbose_name or self.field.name.replace('_', ' ').title(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
.autocomplete-filter-widget {
|
||||
margin-bottom: 10px;
|
||||
padding: 8px;
|
||||
border: 1px solid #ddd;
|
||||
background: #f9f9f9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.autocomplete-filter-widget h3 {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.autocomplete-filter-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.autocomplete-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.autocomplete-clear {
|
||||
background: #ba2121;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 4px 8px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.autocomplete-clear:hover {
|
||||
background: #a41e1e;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single {
|
||||
height: 28px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 26px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single .select2-selection__arrow {
|
||||
height: 26px;
|
||||
right: 4px;
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function () {
|
||||
$('.autocomplete-filter-widget').each(function () {
|
||||
let $widget = $(this);
|
||||
let $input = $widget.find('.autocomplete-input');
|
||||
let $hiddenInput = $widget.find('.autocomplete-hidden');
|
||||
let $clearBtn = $widget.find('.autocomplete-clear');
|
||||
let relatedUrl = $input.data('related-url');
|
||||
let placeholder = $input.attr('placeholder');
|
||||
|
||||
// Initialize Select2
|
||||
$input.select2({
|
||||
ajax: {
|
||||
url: relatedUrl,
|
||||
dataType: 'json',
|
||||
delay: 250,
|
||||
data: function (params) {
|
||||
return {
|
||||
term: params.term,
|
||||
page: params.page || 1
|
||||
};
|
||||
},
|
||||
processResults: function (data, params) {
|
||||
params.page = params.page || 1;
|
||||
return {
|
||||
results: data.results.map(function (item) {
|
||||
return {
|
||||
id: item.id,
|
||||
text: item.text
|
||||
};
|
||||
}),
|
||||
pagination: {
|
||||
more: data.pagination && data.pagination.more
|
||||
}
|
||||
};
|
||||
},
|
||||
cache: true
|
||||
},
|
||||
placeholder: placeholder,
|
||||
allowClear: true,
|
||||
minimumInputLength: 1,
|
||||
width: '250px'
|
||||
});
|
||||
|
||||
// Handle selection
|
||||
$input.on('select2:select', function (e) {
|
||||
let data = e.params.data;
|
||||
$hiddenInput.val(data.id);
|
||||
updateUrl();
|
||||
});
|
||||
|
||||
// Handle clearing
|
||||
$input.on('select2:clear', function (e) {
|
||||
$hiddenInput.val('');
|
||||
updateUrl();
|
||||
});
|
||||
|
||||
// Clear button functionality
|
||||
$clearBtn.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$input.val(null).trigger('change');
|
||||
$hiddenInput.val('');
|
||||
updateUrl();
|
||||
});
|
||||
|
||||
function updateUrl() {
|
||||
let currentUrl = new URL(window.location);
|
||||
let lookupKwarg = $hiddenInput.data('lookup-kwarg');
|
||||
let value = $hiddenInput.val();
|
||||
|
||||
if (value) {
|
||||
currentUrl.searchParams.set(lookupKwarg, value);
|
||||
} else {
|
||||
currentUrl.searchParams.delete(lookupKwarg);
|
||||
}
|
||||
|
||||
// Reset to first page when filtering
|
||||
currentUrl.searchParams.delete('p');
|
||||
|
||||
window.location.href = currentUrl.toString();
|
||||
}
|
||||
});
|
||||
});
|
||||
})(django.jQuery);
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
{% load i18n %}
|
||||
<div class="autocomplete-filter-widget">
|
||||
<h3>{% trans "By" %} {{ field_verbose_name }}</h3>
|
||||
<div class="autocomplete-filter-controls">
|
||||
<select class="autocomplete-input"
|
||||
data-related-url="{{ related_url }}"
|
||||
placeholder="{{ placeholder }}">
|
||||
{% if lookup_val %}
|
||||
{% for choice in choices %}
|
||||
{% if choice.selected %}
|
||||
<option value="{{ choice.value }}" selected>{{ choice.display }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</select>
|
||||
<input type="hidden"
|
||||
class="autocomplete-hidden"
|
||||
data-lookup-kwarg="{{ lookup_kwarg }}"
|
||||
value="{{ lookup_val }}">
|
||||
{% if lookup_val %}
|
||||
<a href="#" class="autocomplete-clear">{{ clear_text }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Reference in a new issue