1. 如何修改编辑页面的布局
效果图:
(1)xadmin.py文件中导入相关的类
import xadmin
from xadmin.layout import Fieldset, Main, Side, Row
from .models import Course
(2) xadmin.py文件中自定义模型管理类
class NewCourseAdmin(object):
list_display = ["name", "desc", "detail", "degree", "learn_times", "students"]
search_fields = ["name", "desc", "teacher__name", "detail", "degree", "students"]
list_filter = ["name", "teacher__name", "desc", "detail", "degree", "learn_times", "students"]
list_editable = ["degree", "desc"]
def get_form_layout(self):
# 此条件判断的意思是只有编辑页面才按照下面的布局
# 新增页面还按照原始的布局
if self.org_obj:
self.form_layout = (
Main(
Fieldset("讲师信息",
"teacher", "course_org",
css_class='unsort no_title'
),
Fieldset("基本信息",
"name", "desc",
Row("learn_times", "degree"),
Row("category", "tag"),
"youneed_know", "teacher_tell", "detail"
),
),
Side(
Fieldset("访问信息",
"students", "fav_nums", "click_nums", "add_time"
),
),
Side(
Fieldset("选择信息",
"is_banner", "is_classic"
)
)
)
return super(NewCourseAdmin, self).get_form_layout()
(3) xadmin.py文件中注册模型类
xadmin.site.register(Course, NewCourseAdmin)
2. 如何让用户可以登录xadmin,并过滤列表中用户自己的数据
xadmin.py中的定义的模型管理类如下:重写queryset方法,根据当前用户是超级管理员用户还是teacher用户对列表页数据进行过滤
class NewCourseAdmin(object):
list_display = ["name", "desc", "detail", "degree", "learn_times", "students"]
search_fields = ["name", "desc", "teacher__name", "detail", "degree", "students"]
list_filter = ["name", "teacher__name", "desc", "detail", "degree", "learn_times", "students"]
list_editable = ["degree", "desc"]
def queryset(self):
qs = super(NewCourseAdmin, self).queryset()
if not self.request.user.is_superuser:
try:
teacher = self.request.user.teacher
qs = qs.filter(teacher=teacher)
except Exception as err:
qs = qs.filter(id__lt=0)
return qs
3. xadmin.py中的定义的模型管理类如下:重写save_models方法控制保存和修改数据的逻辑
class UserCourseAdmin(object):
list_display = ["user", "course", "add_time"]
search_fields = ["user", "course"]
list_filter = ["user", "course", "add_time"]
def save_models(self):
# 新增或修改都会调用save_models方法
# 但是新增的时候obj.id为:None, 修改的时候obj.id为具体的id值
obj = self.new_obj
if obj.id is None:
obj.save()
course = obj.course
course.students += 1
course.save()
4. 同一张表的不同数据使用不同的管理器进行管理
(1) models.py中模型类的定义: 核心是:BannerCourse继承自Course,而且增加了一个类属性:proxy = True
class Course(BaseModel):
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE, verbose_name="讲师")
course_org = models.ForeignKey(CourseOrg, null=True, blank=True, on_delete=models.CASCADE, verbose_name="课程机构")
name = models.CharField(max_length=50, verbose_name="课程名")
desc = models.CharField(max_length=300, verbose_name="课程描述")
learn_times = models.IntegerField(verbose_name="学习时长(分钟数)", default=0)
degree = models.CharField(verbose_name="难度", choices=(("cj", "初级"), ("zj", "中级"), ("gj", "高级")), max_length=2)
students = models.IntegerField(default=0, verbose_name='学习人数')
fav_nums = models.IntegerField(default=0, verbose_name='收藏人数')
click_nums = models.IntegerField(default=0, verbose_name="点击数")
notice = models.CharField(max_length=255, verbose_name="课程公告", default="")
category = models.CharField(default=u"后端开发", max_length=20, verbose_name="课程类别")
tag = models.CharField(default="", verbose_name="课程标签", max_length=10)
youneed_know = models.CharField(default="", max_length=300, verbose_name="课程须知")
teacher_tell = models.CharField(default="", max_length=300, verbose_name="老师告诉你")
detail = models.TextField(verbose_name="课程详情")
image = models.ImageField(upload_to="courses/%Y/%m", verbose_name="封面图", max_length=100)
is_banner = models.BooleanField(default=False, verbose_name="是否广告位")
is_classic = models.BooleanField(default=False, verbose_name="是否经典")
class Meta:
verbose_name = "课程信息"
verbose_name_plural = verbose_name
class BannerCourse(Course):
class Meta:
verbose_name = "轮播课程"
verbose_name_plural = verbose_name
# 注意:增加此属性的作用是不在生成一个新的表,此模型类只是一个代理表
proxy = True
(2) xadmin.py中的代码
import xadmin
from .models import Course, BannerCourse
class CourseAdmin(object):
list_display = ["name", "desc", "detail", "degree", "learn_times", "students"]
search_fields = ["name", "desc", "teacher__name", "detail", "degree", "students"]
list_filter = ["name", "teacher__name", "desc", "detail", "degree", "learn_times", "students"]
list_editable = ["degree", "desc"]
class BannerCourseAdmin(object):
list_display = ["name", "desc", "detail", "degree", "learn_times", "students"]
search_fields = ["name", "desc", "teacher__name", "detail", "degree", "students"]
list_filter = ["name", "teacher__name", "desc", "detail", "degree", "learn_times", "students"]
list_editable = ["degree", "desc"]
def queryset(self):
qs = super().queryset()
qs = qs.filter(is_banner=True)
return qs
xadmin.site.register(Course, CourseAdmin)
xadmin.site.register(BannerCourse, BannerCourseAdmin)
5. 通过在model中定义方法将图片显示在列表页
效果图:
models.py中增加一个方法,用来拼接html和image的url
from django.utils.safestring import mark_safe
class Course(BaseModel):
....此处省略字段
image = models.ImageField(upload_to="courses/%Y/%m", verbose_name="封面图", max_length=100)
def show_image(self):
return mark_safe("<img src='{}'>".format(self.image.url))
# 定义显示图片方法列在后台显示的名称
show_image.short_description = "图片"
def goto_course(self):
return mark_safe("<a href='/course_detail/{}/' title='跳转至{}详情页' target='_blank'>跳转</a>".format(self.id, self.name))
# 定义跳转到课程在后台显示的名称
goto_course.short_description = "跳转至课程"
xadmin.py中直接将方法名写到list_display属性列表中即可
6. 配置列表页允许编辑、只读字段、列聚合、排除字段、默认的排序
注意的是:模型类中设置的必填字段,不能设置到只读字段readonly_fields和排除字段exclude里面去,否则保存的时候程序会报错
class CourseAdmin(object):
# 允许在列表页编辑
list_editable = ["degree", "desc"]
# 将字段设置为只读
readonly_fields = ["click_nums", "fav_nums", "students"]
# 列聚合,可用的值:"count","min","max","avg", "sum"
aggregate_fields = {"learn_times": "sum"}
# 编辑页面排除某些字段
# exclude = ["add_time"]
# 进入列表页时默认的排序字段
ordering = ["-click_nums"]
7. 通过model_icon修改model的图标
(1)图标网址:
https://fontawesome.dashgame.com/
class CourseAdmin(object):
# 图标配置
model_icon = "fa fa-file-text-o"
8. 通过inlines配置多张表的一次性编辑
效果图:
(1)xadmin.py中代码,一门课程Couser可以有多个章节Lesson,也可以有多个课程资源CourseResource
class LessonInline(object):
model = Lesson
# 设置章节的样式为tab标签切换,节省空间,看着清晰
style = "tab"
# 设置显示几个空的tab页
extra = 1
class CourseResourceInline(object):
model = CourseResource
style = "tab"
extra = 1
# inline中也可以配置跟模型管理类一样的属性功能
exclude = ["add_time"]
class CourseAdmin(object):
list_display = ["name", "desc", "detail", "degree", "learn_times", "students", "show_image", "goto_course"]
search_fields = ["name", "desc", "teacher__name", "detail", "degree", "students"]
list_filter = ["name", "teacher__name", "desc", "detail", "degree", "learn_times", "students", "add_time"]
# 编辑一对象时,可以直接编辑多对象
inlines = [LessonInline, CourseResourceInline]
xadmin.site.register(Course, CourseAdmin)