django中xadmin更进阶的开发

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)

猜你喜欢

转载自blog.csdn.net/weixin_42289273/article/details/115127992