django admin 后台样式默认情况下都是默认的样式,有时候我们需要在 admin 显示一张图片、或者更改一个文案的显示颜色等等,该怎办呢?
以下方法采用的是在 model 里更改,也可以在 admin 里面更改。
原理:新增自定义字段,然后给该字段渲染时赋予 HTML 标签(标签有的属性都可以使用)
1. 在 model 里增加想要显示的字段:thumb_shouw
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth import get_user_model
from django.utils.html import format_html
# from django.template.defaultfilters import slugify
# from ckeditor.fields import RichTextField # 不包含上传文件
from ckeditor_uploader.fields import RichTextUploadingField # 包含上传文件
from pyquery import PyQuery as pq # pip install pyquery, 获取到html中的img图片地址返回
# from pypinyin import lazy_pinyin # pip install pypinyin
from uuslug import slugify # pip install django-uuslug
class Article(models.Model):
"""
主题表/文章表
"""
title = models.CharField(max_length=128, unique=True, verbose_name="标题")
slug = models.SlugField(max_length=128, unique=True, verbose_name="url标识符")
content = RichTextUploadingField(verbose_name="内容", config_name='awesome_ckeditor')
node = models.ForeignKey(Node, on_delete=models.DO_NOTHING, verbose_name="所属节点")
user = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name="user_article", verbose_name="作者")
source = models.ForeignKey(Source, on_delete=models.DO_NOTHING, verbose_name="来源", blank=True, null=True)
tags = models.ManyToManyField(Tag, verbose_name="标签", related_name="tags_article", blank=True)
num_views = models.IntegerField(default=0, verbose_name="浏览数量")
num_favorites = models.IntegerField(default=0, verbose_name="收藏数量")
last_answerer = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name="last_answerer_article",
verbose_name="最后回复者", blank=True,
null=True)
show_status = models.BooleanField(default=True, verbose_name="显示状态")
time_create = models.DateTimeField(auto_now_add=True, verbose_name="发表时间")
time_update = models.DateTimeField(blank=True, null=True, auto_now=True, verbose_name="更新时间")
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Article, self).save(*args, **kwargs)
# 获取后台文本编辑器图文内容中图片url地址
def get_content_img_url(self):
temp = Article.objects.filter(pk=str(self.id)).values('content') # values获取Article数据表中的content字段内容
html = pq(temp[0]['content']) # pq方法获取编辑器html内容
# print(html, "\n", "----")
img_path = pq(html)('img').attr('src') # 截取html内容中的路径
# print("pic", img_path)
return img_path # 返回第一张图片路径
# 显示文章的缩略图
def thumb_show(self):
if self.get_content_img_url():
# 如果加了跳转到其他地方超链接,最好不要在 admin 里面不要把该字段加入到 list_display_links
return format_html(
'<span><a href="{}"><img src="{}"/>{}</a></span>', self.get_content_img_url(), self.get_content_img_url(), "这里是缩略图")
else:
return format_html('<span style="color:{}">{}</span>', "red", "暂无缩略图")
# thumb_show.short_description = format_html('<span style="color:red">缩略图</span>') # 新字段的显示的名称,相当于 verbose_name
thumb_show.short_description = format_html('<span class="text">缩略图</span>') # 新字段的显示的名称,相当于 verbose_name
thumb_show.admin_order_field = "-time_update" # 指定排序方式,更新时间倒序排列
# 按钮(此处是其他项目的,放到这里做个例子)
def edit_button(self):
if self.is_agent:
# operations_agent_day_earn = reverse("admin:operations_agentdayearn_changelist")
bind_bill = reverse("admin:operations_bindbill_changelist")
# edit_button = format_html(
# '<button type="button" class="el-button el-button--default"><a href="{}">编辑</a></button>'
# '<button type="button" class="el-button el-button--default"><a href="{}">收益</a></button>',
# str(self.id) + "/change", operations_agent_day_earn + "?agent__id__exact=" + str(self.id))
edit_button = format_html(
'<button type="button" class="el-button el-button--default"><a href="{}">编辑</a></button>'
'<button type="button" class="el-button el-button--default"><a href="{}">收益</a></button>',
str(self.id) + "/change",
bind_bill + "?proportion_rule__agent__username=" + str(self.username))
else:
edit_button = format_html(
'<button type="button" class="el-button el-button--default"><a href="{}">编辑</a></button>',
str(self.id) + "/change")
return edit_button
edit_button.short_description = "操作"
edit_button.admin_order_field = "anchor" # 排序
class Meta:
verbose_name = "文章"
verbose_name_plural = "文章列表"
def __str__(self):
title_short = self.title if len(self.title) < 15 else self.title[:12] + '...'
return "%s %s %s" % (self.id, self.user, title_short)
注:增加按钮就在 format_html 里面返回一个 带 a 标签的 button
2. 在 admin 里启用新增加的字段
# admin.py
from django.contrib import admin
from apps.blog.models import *
class ArticleAdmin(admin.ModelAdmin):
list_display = ['id', 'thumb_shouw', 'title', 'node', 'num_views', 'show_status', 'slug', 'user']
list_display_links = ['id', 'thumb_show', 'title', 'node', 'num_views', 'user']
search_fields = ['title_short', 'user', 'content']
list_editable = ["show_status", ]
# style_fields = {"content": "ueditor"}
readonly_fields = ('slug',)
show_detail_fields = ['show_status', ]
admin.site.register(Article, ArticleAdmin)
3. 重启 django 即可看到效果了
# 官方参考文档
注意:不要跟该 model 里的任何一个字段名相同
class CommentTemporaryAdmin(admin.ModelAdmin):
"""
临时评论表
"""
# 取字段的部分内容
def content_short(self, obj):
return strip_tags(obj.content[:content_short_max])
content_short.short_description = "内容预览" # 新字段的显示的名称
content_shortn.admin_order_field = "content" # 排序
# 启用 content_short
list_display = ['id', 'author', 'content_short']