开发django管理后台

开发django管理后台

  1. 配置admin进行操作
  2. 定制admin
  3. 复用admin

配置admin进行操作

关于django的站点可以参考

采用文档的原话:管理有很多用于定制的钩子,但要注意不要试图专门使用这些钩子。如果您需要提供一个更以流程为中心的接口,抽象掉数据库表和替代的实现细节,那么可能是时候编写自己的视图了

编写blogAdmin代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from django.contrib import admin

# Register your models here.

from .models import Post, Category, Tag

# 注册管理模型
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
# 用于在更改列表中显示更改哪些字段
list_display = ('name','status','is_nav','create_time')
# 使用该fields选项可以在“添加”和“更改”页面上的表单中进行简单的布局更改
fields = ('name','status','is_nav')

@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
list_display = ('name','status','create_time')
fields = ('name','status')

接下激活虚拟环境

执行命令

1
2
3
manage.py createsuperuser
# 启动服务 输入:地址/admin
manage.py runserver

image-20210221155615331

修复小bug

因为我们的模型都是有关联作者的,这个时候实际上fields上面是缺少作者选项的。添加进去就可以了。但是会存在任何作者把创建的内容改为任意作者。这个时候我们需要重写savemodel方法,引用官方文档说明:

image-20210221160636141

修改代码后如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from django.contrib import admin

# Register your models here.

from .models import Post, Category, Tag

# 注册管理模型
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
# 用于在更改列表中显示更改哪些字段
list_display = ('name','status','is_nav','create_time')
# 使用该fields选项可以在“添加”和“更改”页面上的表单中进行简单的布局更改
fields = ('name','status','is_nav')

def save_model(self, request, obj, form, change):
# request获取的是当前已经登录的用户 obj就是对应的注册的模型
obj.owner = request.user
return super(CategoryAdmin,self).save_model(request, obj, form, change)


@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
list_display = ('name','status','create_time')
fields = ('name','status')

def save_model(self, request, obj, form, change):
obj.owner = request.user
return super(TagAdmin,self).save_model(request, obj, form, change)

运行结果如下:

image-20210221161654566

对于django2.1下没有查看的权限可以参考https://blog.csdn.net/u011519550/article/details/100171861

同时:如果只想看到自己建立的数据可以:

image-20210221163755523

细致的配置post管理后台

1.先说2个东西

1
2
3
4
# 一个可以用来解析视图甚至admin,从url中寻找路径
from django.urls import reverse
# 格式化一段html代码
from django.utils.html import format_html

2.增加以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
# 更改列表显示的字段,这里的operator是自定义的方法格式化了一段html代码
list_display = [
'title', 'category', 'status',
'create_time','operator'
]
# 用来配置哪些字段可以作为链接。点击它们就可以进入编辑页面
list_display_links = []
# 配置页面过滤器,意味着可以通过种类的值对数据进行过滤
list_filter = ['category',]
# 配置可以搜索的字段
search_fields = ['title', 'category__name']

# 动作相关的配置
actions_on_top = True
actions_on_bottom = True

# 编辑页面
save_on_top = True

fields = (
('category', 'title'),
'desc',
'status',
'content',
'tag',
)

def operator(self, obj):
return format_html(
'<a href="{}">编辑</a>',
reverse('admin:blog_post_change',args=(obj.id,)) # 这里就是从url中寻找地址
)
operator.short_description = '操作'


def save_model(self, request, obj, form, change):
obj.owner = request.user
return super(TagAdmin,self).save_model(request, obj, form, change)

同理如果我们要增加分类下面有多少文章可以

1
2
3
4
def post_count(self, obj):
return obj.post_set.count()

post_count.short_description = '文章数量'

还有一个问题我们要显示文案的名字需要重写 str方法 每个model需要重写此方法

1
2
def __str__(self):
return self.name

展示为:

image-20210221211507516

照猫画虎(comment与和config)

comment

1
2
3
4
5
6
7
8
9
from django.contrib import admin

from .models import Comment

# Register your models here.

@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('target', 'nickname', 'content', 'website', 'create_time')

config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from django.contrib import admin

from .models import Link, SideBar
# Register your models here.

@admin.register(Link)
class LinkAdmin(admin.ModelAdmin):
list_display = ('title', 'href', 'status', 'weight', 'create_time')

fields = ('title', 'href', 'status', 'weight')

def save_model(self, request, obj, form, change):
obj.owner = request.user
return super(LinkAdmin,self).save_model(self, request, obj, form, change)


@admin.register(SideBar)
class SideBarAdmin(admin.ModelAdmin):
list_display = ('title', 'display_type', 'content', 'create_time')

fields = ('title', 'diplay_type', 'content')

def save_model(self, request, obj, form, change):
obj.owner = request.user
return super(SideBarAdmin,self).save_model(self, request, obj, form, change)

最后效果如下:

image-20210221213728228

admin定制

自定义过滤器

只能过滤当前用户的文章,代码如下:在PostAdmin上面添加

1
2
3
4
5
6
7
8
9
10
11
12
13
class CategoryOwnerFilter(admin.SimpleListFilter):
'''自定义过滤器只展示当前用户分类'''
title = '分类过滤器'
parameter_name = 'owner_category'

def lookups(self, request, model_admin):
return Category.objects.filter(owner=request.user).values_list('id', 'name')

def queryset(self,request,queryset):
category_id = self.value()
if category_id:
return queryset.filter(category_id=self.value())
return queryset

image-20210221220924981

解释说明:

title: 用于展示标题

parameter_name: 查询时url参数的名字相当于?owner_category=1,可以根据配置简答的过滤器来观察参数

lookups: 返回要展示的内容和查询用的id

queryset: 根据url Query的内ring返回列表页数据。 ?owner_category=1 那么self.value就是1

列表数据过滤

解决用户在列表页只看到自己创建的文章

在PostAdmin中重写get_queryset方法

1
2
3
def get_queryset(self, request):
qs = super(PostAdmin,self).get_queryset(request)
return qs.filter(owner=request.user)

image-20210221222501537

admin编辑页面配置

1
exclude = ('owner',) # 可以用于排除不需要什么样的字段

fieldsets控制页面布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fieldsets = (
('基础配置',{
'description': '基础配置描述',
'fields': (
('title', 'category'),
'status'
)
}),
('内容',{
'fields':(
'desc',
'content'
),
}),
('额外信息',{
'classes': ('collapse',),
'fields': ('tag', )
})
)

image-20210221223957741

自定义静态资源引入

在PostAdmin下:

1
2
3
4
5
class Media:
css = {
"all": ("https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css",)
}
js = ("https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/js/bootstrap.bundle.js",)

自定义form

利用modelForm可以定制,比如文章描述字段希望是textarea

Form是和model耦合在一起的。Form的逻辑和model是一致的,model是对数据库字段的抽象,form是对用户输入以及model展示数据的抽象

1
2
3
4
5
6
7
8
9
from django import forms
class PostAdminForm(forms.ModelForm):
desc = forms.CharField(widget=forms.Textarea, label='摘要', required=False)


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
form = PostAdminForm
'''其余省略'''

image-20210221230620789

同一页面编辑关联数据

分类下面可以编辑文章

1
2
3
4
5
6
7
8
9
10
class PostInline(admin.TabularInline): # 也有stackedInline
fields = ('title', 'desc')
extra = 1 # 这控制了表单集除初始表单外还将显示的其他表单的数量。默认值为3
model = Post

# 注册管理模型
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
inlines = [PostInline,]
'''其余省略'''

image-20210221231542155

定制站点

讲文章分类等数据的管理与用户模块等分开

定义一个custom_site.py

1
2
3
4
5
6
7
8
from django.contrib.admin import AdminSite

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

custom_site = CustomSite(name='cus_admin')

PostAdmin中修改为

1
2
3
4
5
from djwwj.custom_site import custom_site
@admin.register(Post, site=custom_site)
# 以及调整链接
reverse('cus_admin:blog_post_change',args=(obj.id,)) # 这里就是从url中寻找地址 /admin/blog/post/1/change/
)

最后更改url

1
2
3
4
5
6
from .custom_site import custom_site

urlpatterns = [
url(r'^admin/', custom_site.urls),
url(r'^super_admin/',admin.site.urls)
]

其实就是通过两套url对业务进行了划分

权限和用户

用户以及权限可以参考文档

https://zhuanlan.zhihu.com/p/26188198

https://docs.djangoproject.com/zh-hans/3.1/topics/auth/default/

https://docs.djangoproject.com/zh-hans/3.1/topics/auth/customizing/

操作日志

如果是大型项目针对业务可以参考 https://www.cnblogs.com/gaosai/p/10322924.html

关于自带的LogEntry 参考https://www.wandouip.com/t5i330704/

1
2
3
4
5
from django.contrib.admin.models import LogEntry

@admin.register(LogEntry, site=custom_site)
class LogEntryAdmin(admin.ModelAdmin):
list_display = ['object_repr','object_id','action_flag','user','change_message']

image-20210222014105835