mod: select2 admin and settings constants
This commit is contained in:
@@ -1,13 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from django import forms
|
||||
from django.contrib import admin
|
||||
from django.db import models
|
||||
from django.forms import TextInput, Textarea
|
||||
from django.urls import reverse
|
||||
from django_select2.forms import Select2TagWidget
|
||||
from web.models import TbContent
|
||||
from web.add_function import safe_html_special_symbols
|
||||
from cadpoint import settings
|
||||
|
||||
|
||||
class AjaxCommaSeparatedSelect2TagWidget(Select2TagWidget):
|
||||
"""
|
||||
Select2-виджет для `taggit`.
|
||||
|
||||
Select2 в браузере работает с массивом значений, а `taggit` ждёт строку
|
||||
с тегами через запятую. Поэтому здесь есть конвертация туда и обратно.
|
||||
"""
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
# Select2 присылает список значений, а `taggit` ожидает строку вида
|
||||
# "tag-one,tag two,tag-three".
|
||||
values = super().value_from_datadict(data, files, name)
|
||||
if isinstance(values, (list, tuple)):
|
||||
return ",".join(values)
|
||||
return values
|
||||
|
||||
def optgroups(self, name, value, attrs=None):
|
||||
# При редактировании объекта нужно показать уже выбранные теги.
|
||||
# При этом не тащим ВСЕ теги из базы — только те, что уже сохранены.
|
||||
if isinstance(value, (list, tuple)):
|
||||
raw_values = []
|
||||
for item in value:
|
||||
if not item:
|
||||
continue
|
||||
raw_values.extend(str(item).split(","))
|
||||
else:
|
||||
raw_values = str(value or "").split(",")
|
||||
|
||||
values = [item for item in raw_values if item]
|
||||
selected = set(values)
|
||||
subgroup = [
|
||||
self.create_option(name, v, v, v in selected, i)
|
||||
for i, v in enumerate(values)
|
||||
]
|
||||
return [(None, subgroup, 0)]
|
||||
|
||||
|
||||
class AdminContentForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = TbContent
|
||||
fields = '__all__'
|
||||
|
||||
class Media:
|
||||
css = {
|
||||
'all': ('css/admin-select2-theme.css',),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# AJAX-виджет подгружает список тегов лениво, а здесь мы оставляем
|
||||
# только уже выбранные значения, чтобы не тащить все теги из базы при
|
||||
# открытии формы и не провоцировать лишние запросы к SQLite.
|
||||
if self.is_bound:
|
||||
if hasattr(self.data, 'getlist'):
|
||||
tag_values = self.data.getlist('tags')
|
||||
else:
|
||||
raw_values = self.data.get('tags', [])
|
||||
tag_values = raw_values if isinstance(raw_values, list) else [raw_values]
|
||||
tag_choices = [(value, value) for value in tag_values if value]
|
||||
elif self.instance.pk:
|
||||
tag_choices = [
|
||||
(name, name)
|
||||
for name in self.instance.tags.order_by('name').values_list('name', flat=True)
|
||||
]
|
||||
else:
|
||||
tag_choices = []
|
||||
|
||||
self.fields['tags'].widget = AjaxCommaSeparatedSelect2TagWidget(
|
||||
attrs={
|
||||
'data-ajax--url': reverse('web_tag_autocomplete'),
|
||||
'data-ajax--cache': 'true',
|
||||
'data-ajax--data-type': 'json',
|
||||
'data-ajax--delay': settings.SELECT2_AJAX_DELAY_MS,
|
||||
'data-token-separators': settings.SELECT2_TOKEN_SEPARATORS,
|
||||
'data-minimum-input-length': settings.SELECT2_MINIMUM_INPUT_LENGTH,
|
||||
},
|
||||
choices=tag_choices,
|
||||
)
|
||||
|
||||
|
||||
# Register your models here.
|
||||
class AdminContent(admin.ModelAdmin):
|
||||
form = AdminContentForm
|
||||
search_fields = ['szContentHead', 'szContentIntro', 'szContentBody',
|
||||
'szContentKeywords', 'szContentDescription']
|
||||
list_display = ('id', 'ContentHeadSafe', 'tag_list', 'bContentPublish', 'tdContentPublishUp')
|
||||
@@ -49,7 +134,10 @@ class AdminContent(admin.ModelAdmin):
|
||||
return safe_html_special_symbols(obj.szContentHead)
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).prefetch_related('tags')
|
||||
queryset = super().get_queryset(request)
|
||||
if request.resolver_match and request.resolver_match.url_name == 'web_tbcontent_changelist':
|
||||
return queryset.prefetch_related('tags')
|
||||
return queryset
|
||||
|
||||
def tag_list(self, obj):
|
||||
return u", ".join(o.name for o in obj.tags.all())
|
||||
|
||||
Reference in New Issue
Block a user