35f2091e0b
- Post (категории, важное/закреплено/опубликовано, автор) + PostComment; тело — HTML из TinyMCE, санитизация nh3 в save() (XSS), загрузка картинок отдельным endpoint с проверкой содержимого (data:-URI вырезаются) - Лента с полным выводом постов, фильтры, сворачивание длинных; детальная страница с комментариями; edit — автор/staff, delete — автор - Публикация постов в каналы Mattermost (mattermost_targets), сигналы - Тесты (40): публикация/черновики, права, санитизация, картинки, выравнивание, комментарии, лента/дашборд Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
45 lines
1.3 KiB
Python
45 lines
1.3 KiB
Python
from django import forms
|
|
from django.contrib import admin
|
|
from tinymce.widgets import TinyMCE
|
|
from unfold.admin import ModelAdmin, TabularInline
|
|
|
|
from apps.feed.models import Post, PostComment
|
|
|
|
|
|
class PostAdminForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Post
|
|
fields = '__all__'
|
|
widgets = {'body': TinyMCE()}
|
|
|
|
|
|
class PostCommentInline(TabularInline):
|
|
model = PostComment
|
|
extra = 0
|
|
readonly_fields = ['author', 'created_at']
|
|
fields = ['author', 'text', 'created_at']
|
|
|
|
|
|
@admin.register(Post)
|
|
class PostAdmin(ModelAdmin):
|
|
form = PostAdminForm
|
|
list_display = ['title', 'category', 'is_important', 'is_pinned',
|
|
'is_published', 'author', 'created_at']
|
|
list_filter = ['category', 'is_important', 'is_pinned', 'is_published']
|
|
search_fields = ['title', 'body']
|
|
list_select_related = ['author']
|
|
ordering = ['-created_at']
|
|
inlines = [PostCommentInline]
|
|
|
|
def save_model(self, request, obj, form, change):
|
|
if not change and not obj.author:
|
|
obj.author = request.user
|
|
super().save_model(request, obj, form, change)
|
|
|
|
|
|
@admin.register(PostComment)
|
|
class PostCommentAdmin(ModelAdmin):
|
|
list_display = ['post', 'author', 'text', 'created_at']
|
|
search_fields = ['text']
|
|
list_select_related = ['post', 'author']
|