Django ブログサイト admin.py システム管理機能

2020/07/04 (更新:2020/11/19)

システム管理機能のカスタマイズ定義です。
本サイトで使用しているカスタマイズのオプションです。

list_display一覧の表示項目を設定します
ordering一覧の表示順序を設定します
list_filterサイドバーにフィルタを表示し対象項目を設定します
search_fields検索ボックスを表示し検索項目を設定します
raw_id_fields関連項目の編集コントロールをプルダウンからテキストフィールドに変更します

投稿者

Django サイト管理機能のユーザー(スタッフ)に紐づけます。
次の項目を編集します。

author_nameDjango ユーザーのユーザー名(ユーザーの変更へのリンク)
emailDjango ユーザーのメールアドレス
post該当記事の件数(投稿者ブログのリンク)

Django ユーザーと一緒に管理するため、本モデル単体の登録機能と削除機能を無効化します。

Author

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('title_text', 'author_name', 'email', 'flags', 'post')
    ordering = ('id',)
    search_fields = ('author_name', 'title_text', 'email')
    exclude = ('user',)

    def author_name(sef, obj):
        href = reverse('admin:auth_user_change', args=(obj.user.id,))
        return format_html('<a href="{}">{}</a>', href, obj.user.username)

    def post(sef, obj):
        href = reverse('blog:index', args=(obj.user.username,))
        return format_html('<a href="{}" target="blog">{}</a>', href, obj.post_set.count())

    def email(sef, obj):
        return obj.user.email

    def has_add_permission(self, request):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

admin.site.register(models.Author, AuthorAdmin)

共通カスタマイズ定義

管理者ユーザーは全機能を使用可とし、投稿者(スタッフ)は投稿者モデルへのアクセスを制限します。
各モデルのカスタマイズ定義は本クラスを継承します。

AplModel

def set_author_by_user(request, org_list, item_name):
    edit_list = list(org_list)
    if not request.user.is_superuser:
        edit_list.remove(item_name)
    return edit_list    

class AplModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        queryset = super().get_queryset(request)
        if not request.user.is_superuser:
            queryset = queryset.filter(author=request.user.author)
        return queryset

    def get_list_display(self, request):
        return set_author_by_user(request, super().get_list_display(request), 'author')

    def get_list_filter(self, request):
        return set_author_by_user(request, super().get_list_filter(request), 'author')
    
    def get_exclude(self, request, obj=None):
        exclude = super().get_exclude(request, obj)
        if not request.user.is_superuser:
            if not exclude:
                exclude = []
            exclude.append('author')
        return exclude
    
    def save_model(self, request, obj, form, change):
        if not request.user.is_superuser:
            obj.author = request.user.author
        obj.save()
RelatedModel

class RelatedModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        queryset = super().get_queryset(request)
        if not request.user.is_superuser:
            queryset = queryset.filter(post__author=request.user.author)
        return queryset
    
    def author(sef, obj):
        return obj.post.author
    
    def get_list_display(self, request):
        return set_author_by_user(request, super().get_list_display(request), 'author')
    
    def get_list_filter(self, request):
        return set_author_by_user(request, super().get_list_filter(request), 'post__author')

記事属性

次の項目を編集します。

title_text記事内容のタイトル(記事のリンク)
category紐づくカテゴリの件数
Post

class PostAdmin(AplModelAdmin):
    list_display = ['id', 'author', 'title_text', 'status', 'template_text', 'category', 'view_count']
    ordering = ('author', 'id')
    list_filter = ['author', 'status']
    search_fields = ('template_text',)
    
    def title_text(sef, obj):
        href = reverse('blog:detail', args=(obj.author.user.username, obj.id))
        return format_html('<a href="{}" target="blog">{}</a>', href, obj.get_title_text())

    def category(sef, obj):
        return obj.postcategory_set.count()

admin.site.register(models.Post, PostAdmin)

記事内容

次の項目を編集します。

lang言語名
title_text記事のリンク
summary_textサマリー抜粋
PostContent

class PostContentAdmin(RelatedModelAdmin):
    list_display = ('id', 'post', 'language_code_short', 'title_text_link', 'summary_text_short')
    ordering = ('post', 'id', 'language_code')
    list_filter = ('post__author', 'language_code')
    search_fields = ('language_code', 'title_text', 'summary_text')
    raw_id_fields = ('post',)

    def language_code_short(sef, obj):
        return obj.language_code
    language_code_short.short_description = 'lang'

    def title_text_link(sef, obj):
        href = utils.reverse('blog:detail', obj.language_code, obj.post.author.user.username, obj.post.id)
        return format_html('<a href="{}" target="blog">{}</a>', href, obj.title_text)
    title_text_link.short_description = "title_text"

    def summary_text_short(sef, obj):
        return obj.summary_text[:20]
    summary_text_short.short_description = "summary_text"

admin.site.register(models.PostContent, PostContentAdmin)

カテゴリ

Category

class CategoryAdmin(AplModelAdmin):
    list_display = ('author', 'category_text', 'order_number')
    ordering = ('author', 'order_number')
    list_filter = ('author',)
    search_fields = ('category_text',)
    
admin.site.register(models.Category, CategoryAdmin)

記事カテゴリ関連

PostCategory

class PostCategoryAdmin(RelatedModelAdmin):
    list_display = ('author', 'category', 'post')
    ordering = ('category', 'post')
    list_filter = ('post__author', 'category')
    search_fields = ('category', 'post')
    raw_id_fields = ('category', 'post')
    
admin.site.register(models.PostCategory, PostCategoryAdmin)

コメント

Comment

class CommentAdmin(RelatedModelAdmin):
    list_display = ('author', 'id', 'comment_text', 'status', 'client_text', 'post', 'parent', 'created_date')
    ordering = ('-id',)
    list_filter = ('post__author', 'status',)
    search_fields = ('comment_text', 'post', 'client_text')

admin.site.register(models.Comment, CommentAdmin)