fix_test #4

Merged
nikdizell merged 4 commits from fix_test into main 2026-04-09 18:47:19 +03:00
Showing only changes of commit cf0d48c800 - Show all commits

View File

@ -3,7 +3,8 @@ from django.utils import timezone
from django.utils.html import format_html from django.utils.html import format_html
from django.urls import path from django.urls import path
from django.shortcuts import render from django.shortcuts import render
from django.contrib import messages from django.db import models
from django_ckeditor_5.widgets import CKEditor5Widget
from .models import Home, Solution, Competence, Recall, CallbackRequest, PageView from .models import Home, Solution, Competence, Recall, CallbackRequest, PageView
@ -11,38 +12,103 @@ from .models import Home, Solution, Competence, Recall, CallbackRequest, PageVie
# ===== BASE ADMIN CLASSES ===== # ===== BASE ADMIN CLASSES =====
class BaseContentAdmin(admin.ModelAdmin): class BaseContentAdmin(admin.ModelAdmin):
"""Общий базовый класс для контентных моделей.""" """
Базовый класс для контентных моделей.
CKEditor, actions публикации, date_hierarchy.
"""
list_display_links = ('id', 'title') list_display_links = ('id', 'title')
list_editable = ('is_published',) list_editable = ('is_published',)
list_filter = ('time_create', 'is_published') list_filter = ('time_create', 'is_published')
search_fields = ('title',) search_fields = ('title',)
date_hierarchy = 'time_create'
actions = ['make_published', 'make_unpublished']
formfield_overrides = {
models.TextField: {'widget': CKEditor5Widget(config_name='default')},
}
def make_published(self, request, queryset):
updated = queryset.update(is_published=True)
self.message_user(request, f'{updated} объектов опубликовано.')
make_published.short_description = 'Опубликовать выбранные'
def make_unpublished(self, request, queryset):
updated = queryset.update(is_published=False)
self.message_user(request, f'{updated} объектов снято с публикации.')
make_unpublished.short_description = 'Снять с публикации'
# ===== MODEL ADMINS ===== # ===== MODEL ADMINS =====
@admin.register(Home) @admin.register(Home)
class HomeAdmin(BaseContentAdmin): class HomeAdmin(BaseContentAdmin):
# Поля: title, content, home_image, time_create, time_update, is_published
list_display = ('id', 'title', 'time_create', 'is_published') list_display = ('id', 'title', 'time_create', 'is_published')
search_fields = ('title', 'content') search_fields = ('title', 'content')
fieldsets = (
(None, {
'fields': ('title', 'is_published'),
}),
('Содержание', {
'fields': ('content', 'home_image'),
'description': 'Основной текст главной страницы.',
}),
)
@admin.register(Solution) @admin.register(Solution)
class SolutionAdmin(BaseContentAdmin): class SolutionAdmin(BaseContentAdmin):
# Поля: title, description, implementation, closing, time_create, time_update, is_published
list_display = ('id', 'title', 'time_create', 'is_published') list_display = ('id', 'title', 'time_create', 'is_published')
search_fields = ('title', 'description', 'implementation') search_fields = ('title', 'description', 'implementation')
fieldsets = (
(None, {
'fields': ('title', 'is_published'),
}),
('Содержание', {
'fields': ('description', 'implementation', 'closing'),
'description': 'Описание, реализация и заключение по проекту.',
}),
)
@admin.register(Competence) @admin.register(Competence)
class CompetenceAdmin(BaseContentAdmin): class CompetenceAdmin(BaseContentAdmin):
# Поля: title, content, photo, time_create, time_update, is_published
list_display = ('id', 'title', 'time_create', 'is_published') list_display = ('id', 'title', 'time_create', 'is_published')
search_fields = ('title', 'content') search_fields = ('title', 'content')
fieldsets = (
(None, {
'fields': ('title', 'is_published'),
}),
('Содержание', {
'fields': ('content', 'photo'),
'description': 'Описание компетенции и фото.',
}),
)
@admin.register(Recall) @admin.register(Recall)
class RecallAdmin(BaseContentAdmin): class RecallAdmin(BaseContentAdmin):
# Поля: title, content, scan, time_create, time_update, is_published
list_display = ('id', 'title', 'time_create', 'scan', 'is_published') list_display = ('id', 'title', 'time_create', 'scan', 'is_published')
search_fields = ('title', 'content') search_fields = ('title', 'content')
fieldsets = (
(None, {
'fields': ('title', 'is_published'),
}),
('Содержание', {
'fields': ('content', 'scan'),
'description': 'Текст отзыва и скан документа.',
}),
)
# ===== CALLBACK =====
@admin.register(CallbackRequest) @admin.register(CallbackRequest)
class CallbackAdmin(admin.ModelAdmin): class CallbackAdmin(admin.ModelAdmin):
@ -54,16 +120,12 @@ class CallbackAdmin(admin.ModelAdmin):
readonly_fields = ('time_create',) readonly_fields = ('time_create',)
actions = ['mark_as_read', 'mark_as_unread', 'mark_as_processed', 'resend_notification'] actions = ['mark_as_read', 'mark_as_unread', 'mark_as_processed', 'resend_notification']
# ── badge helper ──────────────────────────────────────────────────────────
def new_badge(self, obj): def new_badge(self, obj):
if not obj.is_read: if not obj.is_read:
return format_html('<span style="color:red;font-weight:bold;">🆕 НОВАЯ</span>') return format_html('<span style="color:red;font-weight:bold;">🆕 НОВАЯ</span>')
return '' return ''
new_badge.short_description = 'Статус' new_badge.short_description = 'Статус'
# ── bulk actions ──────────────────────────────────────────────────────────
def mark_as_read(self, request, queryset): def mark_as_read(self, request, queryset):
updated = queryset.update(is_read=True) updated = queryset.update(is_read=True)
self.message_user(request, f'{updated} заявок отмечены как прочитанные') self.message_user(request, f'{updated} заявок отмечены как прочитанные')
@ -85,8 +147,6 @@ class CallbackAdmin(admin.ModelAdmin):
self.message_user(request, f'Уведомления отправлены для {count} заявок') self.message_user(request, f'Уведомления отправлены для {count} заявок')
resend_notification.short_description = 'Переотправить email уведомления' resend_notification.short_description = 'Переотправить email уведомления'
# ── custom URL + view for stats ───────────────────────────────────────────
def get_urls(self): def get_urls(self):
urls = super().get_urls() urls = super().get_urls()
custom_urls = [ custom_urls = [
@ -117,11 +177,8 @@ class CallbackAdmin(admin.ModelAdmin):
} }
return render(request, 'admin/callback_stats.html', context) return render(request, 'admin/callback_stats.html', context)
# ── FIX: removed get_queryset message_user spam ───────────────────────────
# Previously, a warning banner was shown on EVERY request to the changelist,
# including background requests. Removed entirely — the new_badge column
# and base_site.html header notification already surface unread counts.
# ===== PAGE VIEWS =====
@admin.register(PageView) @admin.register(PageView)
class PageViewAdmin(admin.ModelAdmin): class PageViewAdmin(admin.ModelAdmin):
@ -134,7 +191,6 @@ class PageViewAdmin(admin.ModelAdmin):
def get_queryset(self, request): def get_queryset(self, request):
return super().get_queryset(request).order_by('-timestamp') return super().get_queryset(request).order_by('-timestamp')
# PageViews should never be created or edited manually
def has_add_permission(self, request): def has_add_permission(self, request):
return False return False