typeidea——第六章

一、 配置admin

在admin.py中为model.py的每个字段注册至admin后台管理界面:
方法一:

class PostAdmin(admin.ModelAdmin):
    pass
admin.site.register(Post, PostAdmin)

方法二:
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
pass

二、定制site和admin_list

  • 定制site
    typeidea/custom_site.py
from django.contrib.admin import AdminSite


class CustomSite(AdminSite):
    site_header = 'Typeidea'
    site_title = 'Typeidea后台管理'
    index_title = '首页'


custom_site = CustomSite(name='cus_admin')

blog/admin.py

@admin.register(Post, site=custom_site)
class PostAdmin(admin.ModelAdmin):
    pass


@admin.register(Category, site=custom_site)
class CategoryAdmin(admin.ModelAdmin):
    pass


@admin.register(Tag, site=custom_site)
class TagAdmin(admin.ModelAdmin):
    pass

blog/urls.py
url(r'^cus_admin/', custom_site.urls),

  • 定制admin_list
# 显示页面
    list_display = ['title', 'category', 'status', 'owner', 'created_time']
    list_display_links = ['title']

    list_filter = ['category', 'owner']
    search_fields = ['title', 'category__name', 'owner__username']
    show_full_result_count = True

    actions_on_top = True
    actions_on_bottom = True
    date_hierarchy = 'created_time'
    list_editable = ['status']
image.png
fieldsets = (
        ('基础配置', {
            'fields': (('category', 'title'), 'content')
        }),
        ('高级配置', {
            'classes': ('collapse', 'addon'),
            'fields': ('tags',)
        })
    )
image.png

三、自定义字段

def operator(self, obj):
    return format_html(
        '<a href="{}">编辑</a>',
        # '/cus_admin/blog/post/%s/' % obj.id
        reverse('cus_admin:blog_post_change', args=(obj.id,))
    )
# operator.allow_tags = True
operator.short_description = '操作'

四、自定义Form

还是只针对postadmin来增加form, 在blog目录下增加文件(模块)adminforms.py 这里要命名为adminforms而不是forms,只为了跟前台针对用户输入进行处理的form区分开来。里面编写代码,定义form。关于form的作用,我们之前有讲到,form跟model其实是耦合在一起的,或者说form跟model的逻辑是一致的,model是对数据库中字段的抽象,form是对用户输入以及model中要展示数据的抽象。
我们通过form来定制下status这个字段的展示

# adminforms.py
from django import forms


class PostAdminForm(forms.ModelForm):
    status = forms.BooleanField(label="是否删除", required=True)
    desc = forms.CharField(widget=forms.Textarea, label='摘要', required=False)


# admin.py
from .adminforms import PostAdminForm

form = PostAdminForm

五、同时编辑外键和数据Inline

class PostInlineAdmin(admin.TabularInline):
    fields = ('title', 'status')
    extra = 1  # 控制额外多几个
    min_num = 1
    model = Post

class CategoryAdmin(admin.ModelAdmin):
    inlines = [
        PostInlineAdmin
    ]
image.png

六、抽象基础Admin类

在日常开发中经常会有遇到这样的问题,同样的代码亦或是类似的逻辑遍布在项目各处,可能是之前有人通过copy完成的业务功能,也可能是自己编写,恰巧逻辑一样。不管怎么说,这样的代码会导致维护成本的提高。试想一下,如果有一天,这样的逻辑需要修改,那你要修改多少个地方?就算你是维护这个项目很久的“老人”,也可能会输出,遗漏一两处,进而导致线上故障。

所以在开发时我们要时刻保持的理念是——尽量降低后期的维护成本。如何降低呢?自然是降低负担,让后来的程序员在修改代码时不会被之前凌乱的代码“绊倒”。

话不多说,我们先来抽象出一个基类——BaseOwnerAdmin,这个类需要帮忙我们完成两件事:一、重写save方法,save时设置对象的owner;二、重写get_queryset方法,这样让列表页在展示文章或者分类时只能展示当前用户的数据。

# -*- coding:utf-8 -*-
from __future__ import unicode_literals
__author__ = 'cao.yh'
__date__ = '2018/4/5 下午12:02'


from django.contrib import admin


class BaseOwnerAdmin(admin.ModelAdmin):
    """
    针对有Owner属性的数据(文章、分类、标签、侧边栏、友链),重写
    1. save_model - 保证每一条数据都属于当前用户
    2. get_queryset - 保证每个用户只能看到自己的文章
    """
    # 此方法为admin界面显示所有可编辑的Model实例
    def get_queryset(self, request):
        qs = super(BaseOwnerAdmin, self).get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(owner=request.user)


    # 此方法为admin界面用户保存Model实例时的行为:request为HttpRequest实例,obj为model实例,form为ModelForm实例,change为bool值,取决于model实例是新增的还是修改的。
    def save_model(self, request, obj, form, change):
        obj.owner = request.user  # 把request.user保存为model实例的属性
        return super(BaseOwnerAdmin, self).save_model(request, obj, form, change)

遇到的问题

ERRORS: (admin.E108) The value of 'list_display[3]' refers to 'category', which is not a callable, an attribute of 'PostAdmin', or an attribute or method on 'blog.Post'.

System check identified 1 issue (0 silenced).

解决办法:查看PostAdmin中list_display中相关字段的拼写

参考:

https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_queryset
https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容