零基础使用Django2.0.1打造在线教育网站(二十六):xadmin的进阶开发

关于博主

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

                                      微信公众号:  啃饼思录
                                    QQ: 2810706745(啃饼小白)

写在前面

本篇笔记我们将介绍xadmin的进阶开发,具体包括自定义icon,默认排序,字段只读,字段隐藏,搜索框,inlines,一张表分两个model来进行管理添加数据,直接列表页编辑,列表页显示章节数,显示自定义的html代码,列表页定时刷新,字段联动功能,xadmin源码目录简说,xadmin集成富文本等功能,下面我们依次介绍一下。

本篇笔记对应于第二十六篇代码,对应于github的位置是https://github.com/licheetools/eduline

首先需要把我们在前面当Debug=False时,修改的以下代码全部删除掉:


为了解决上述问题,我们这样做:打开eduline/settings.py文件,新增代码如下:

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

同时将里面的STATICFILES_DIRS给注释掉(这一步很重要,否则系统还是去找这个文件,事实上是找不到的,所以还是图片加载不出来):

# STATICFILES_DIRS = [
#     os.path.join(BASE_DIR, "static"),  # 说明静态文件放在哪个目录,记住这里只能用列表或者元组,单一一个元组需要用,结尾
# ]

打开eduline/urls.py文件,新增代码如下:

from eduline.settings import  STATIC_ROOT

 # 配置静态文件上传的访问处理url
    re_path('static/(?P<path>.*)', serve, {"document_root": STATIC_ROOT}),

恢复到Debug=True时的状态。

然后进入到我们的xadmin后台,开始xadmin的进阶开发。

自定义icon

所谓icon其实就是你的功能小图标:

我们以修改邮箱验证码为例,打开users/adminx.py文件,在EmailVerifyRecordAdmin函数新增一行代码:

model_icon = 'fa fa-user'

其实这个样式就是对应于font awesome里面的图标,你可以下载新的源代码对你的目录下的css和fonts文件夹进行替换:

然后刷新一下就出现自己想要的样式icon了。

默认排序,字段只读,字段隐藏

我们以课程为例,来介绍这3个小功能。打开couses/adminx.py文件,在CourseAdmin中加入以下代码:

# 默认排序:以点击数排序
ordering = ['-click_nums']

# 字段只读:点击数只允许读取
readonly_fields = ['click_nums', 'fav_nums']

# 字段隐藏:收藏数隐藏显示
exclude = ['fav_nums']

# 注意字段只读和字段隐藏是冲突的,不允许设置一个字段只读同时隐藏

搜索框

当课程很多时,我们不能以下拉菜单的形式来查找我们的课程,我们需要有搜索框。你已经知道,课程它有一个外键是课程机构,因此我们需要到课程机构里面进行搜索框的配置。打开organization/adminx.py文件,在CourseOrgAdmin函数里面添加一行代码:

# 搜索框,当课程数据量过大时,有课程指向它,会以ajax方式加载
    relfield_style = 'fk-ajax'

inlines添加数据

在这之前,我们新增课程的时候是不能同时新增课程章节信息的,需要跳到另一个页面,这是很麻烦的。所以我们考虑采用inlines来添加数据从而完成在一个页面直接完成章节信息的添加。

打开couses/adminx.py文件,在最顶部新定义一个函数:

# 课程直接添加章节
class LessonInline(object):
    model = Lesson
    extra = 0

# 同时在CourseAdmin中,新增一行代码
# 课程直接添加章节
    inlines = [LessonInline] # 数组,支持多个

刷新一下我们的后台,发现章节信息在课程页面底部出现了:

同时也支持多个添加,比方再添加一个课程资源:

一张表分两个model来进行管理

录播课程与非轮播课程可以分开管理,但是最好是在一张表里显示。打开courses/models.py文件,在course函数下面新增代码

class BannerCourse(Course):  # 注意是继承Course而不是object这个最高类
    class Meta:
        verbose_name = "轮播课程"
        verbose_name_plural = verbose_name
        proxy = True  # 很重要,否则会生成另外一张表,这样设置具有model的功能,但不会生成表

然后打开courses/adminx.py文件,修改之前的代码:

from .models import  BannerCourse

class CourseAdmin(object):
    list_display = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students', 'fav_nums', 'image', 'click_nums',
                    'add_time']  # 一次显示你想出现的多行数据
    search_fields = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students', 'fav_nums', 'image',
                     'click_nums']  # 查询你想要的数据
    list_filter = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students', 'fav_nums', 'image', 'click_nums',
                   'add_time']  # 过滤器
    # # 默认排序:以点击数排序
    # ordering = ['-click_nums']
    #
    # # 字段只读:点击数只允许读取
    # readonly_fields = ['click_nums', 'fav_nums']
    #
    # # 字段隐藏:收藏数隐藏显示
    # exclude = ['fav_nums']
    # # 注意字段只读和字段隐藏是冲突的,不允许设置一个字段只读同时隐藏

    # 课程直接添加章节,课程资源
    inlines = [LessonInline, CourseResourceInline]

    # 过滤列表中的数据
    def queryset(self):
        qs = super(CourseAdmin, self).queryset()
        qs = qs.filter(is_banner=False)
        return qs


class BannerCourseAdmin(object):
    list_display = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students', 'fav_nums', 'image', 'click_nums',
                    'add_time']  # 一次显示你想出现的多行数据
    search_fields = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students', 'fav_nums', 'image',
                     'click_nums']  # 查询你想要的数据
    list_filter = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students', 'fav_nums', 'image', 'click_nums',
                   'add_time']  # 过滤器
    # # 默认排序:以点击数排序
    # ordering = ['-click_nums']
    #
    # # 字段只读:点击数只允许读取
    # readonly_fields = ['click_nums', 'fav_nums']
    #
    # # 字段隐藏:收藏数隐藏显示
    # exclude = ['fav_nums']
    # # 注意字段只读和字段隐藏是冲突的,不允许设置一个字段只读同时隐藏

    # 课程直接添加章节,课程资源
    inlines = [LessonInline, CourseResourceInline]

    # 过滤列表中的数据
    def queryset(self):
        qs = super(BannerCourseAdmin, self).queryset()
        qs = qs.filter(is_banner=True)
        return qs


xadmin.site.register(BannerCourse, BannerCourseAdmin)

然后刷新一下后台页面,发现有2个课程管理:

所以我们还是要配置一下:打开users/adminx.py文件,新增以下代码:

from courses.models import BannerCourse

{'title': '轮播课程', 'url': self.get_model_url(BannerCourse, 'changelist')},

并修改之前的course的verbose_name为普通课程。

就是这个样子:

刷新一下我们的后台页面:

直接列表页编辑

在courses/adminx.py文件的CourseAdmin函数,新增一行代码:

 # 直接列表页编辑
    list_editable = ['degree', 'desc', ]

列表页显示章节数

在courses/adminx.py文件的CourseAdmin和BannerCourseAdmin函数的list_display中,新增显示字段get_zj_nums,刷新后台发现是黑色的英文,我们需要修改,新增一行代码:

get_zj_nums.short_description = "章节数"

显示自定义的html代码

在刚才的页面下面新增以下代码:

def go_to(self):

    from django.utils.safestring import mark_safe
    # 如果不使用mark_safe,系统则会对其进行转义
    return mark_safe("<a href='http://blog.licheetools.top'>跳转</>")
go_to.short_description = "跳转"
就是这个样子:
![](https://upload-images.jianshu.io/upload_images/8964398-e52c998057f7f32d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

## 列表页定时刷新
打开courses/adminx.py文件,在之前的CourseAdmin函数里面,新增一行代码:

refresh_times = 3,5 # 列表页定时刷新3s或者5s

## 字段联动功能
打开courses/adminx.py文件,在之前的CourseAdmin函数里面,新增以下代码:

字段联动

def save_models(self):
    # 在保存课程的时候,统计课程机构的课程数
    obj = self.new_obj
    # 新增课程还没有保存,统计的课程数就会少一个
    obj.save()
    # 必须确定存在
    if obj.course_org is not None:
        # obj实际是一个course对象
        course_org = obj.course_org
        course_org.course_nums = Course.objects.filter(course_org=course_org).count()
        course_org.save()
## xadmin源码目录简说
![](https://upload-images.jianshu.io/upload_images/8964398-8a5ca28f1ab83af8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- locale  对应语言包
- migrations 是数据表的记录
- plugins 每一个后台页面都是一个plugin插件
- static 静态文件夹,里面有js,css
- template 这是xadmin自己使用的html文件
- templatetags  这是tag模板
总而言之,xadmin它是对Django admin的封装和进阶开发,正所谓青出于蓝而胜于蓝就是这个理。

## xadmin集成富文本
首先点击[Xadmin 插件制作](https://xadmin.readthedocs.io/en/docs-chinese/make_plugin.html),我们学着官网的介绍,自己尝试做一个插件:富文本编辑器。
点击[DjangoUeditor](https://github.com/zhangfisher/DjangoUeditor),获取**DjangoUeditor**的安装包,然后按照帮助文档或者下面的要求安装DjangoUeditor。
### 1、安装方法(注意需要转到eduline这个虚拟环境下面才能安装)

方法一:将github整个源码包下载回家,在命令行运行:

python setup.py install
  • 方法二:使用pip工具在命令行运行(推荐): pip install DjangoUeditor### 2、在Django中安装DjangoUeditor 在INSTALL_APPS里面增加DjangoUeditor app,如下: eduline/settings.py文件:

INSTALLED_APPS = ( #........ 'DjangoUeditor', )

### 3、配置urls 

eduline/urls.py文件:

富文本相关path配置

path("ueditor/", include('DjangoUeditor.urls')),
### 4、在models中的使用

courses/models.py文件:

from DjangoUeditor.models import UEditorField

class Course(models.Model):

detail = UEditorField(verbose_name='课程详情', width=600, height=300, imagePath="courses/ueditor/",
                                     filePath="courses/ueditor/", default='')
### 5、书写代码
在xadmin的plugins文件夹下面,新增一个**ueditor.py**文件,在里面新增:

import xadmin

from xadmin.views import BaseAdminPlugin, CreateAdminView, ModelFormAdminView, UpdateAdminView

from DjangoUeditor.models import UEditorField

from DjangoUeditor.widgets import UEditorWidget

from django.conf import settings

class XadminUEditorWidget(UEditorWidget):

def __init__(self,**kwargs):
    self.ueditor_options=kwargs
    self.Media.js = None
    super(XadminUEditorWidget,self).__init__(kwargs)

class UeditorPlugin(BaseAdminPlugin):

def get_field_style(self, attrs, db_field, style, **kwargs):
    if style == 'ueditor':
        if isinstance(db_field, UEditorField):
            widget = db_field.formfield().widget
            param = {}
            param.update(widget.ueditor_settings)
            param.update(widget.attrs)
            return {'widget': XadminUEditorWidget(**param)}
    return attrs
# 在我们生成的页面中放入自己的js文件
def block_extrahead(self, context, nodes):
    js = '<script type="text/javascript" src="%s"></script>' % (settings.STATIC_URL + "ueditor/ueditor.config.js")         #自己的静态目录
    js += '<script type="text/javascript" src="%s"></script>' % (settings.STATIC_URL + "ueditor/ueditor.all.min.js")   #自己的静态目录
    nodes.append(js)

新增页面

xadmin.site.register_plugin(UeditorPlugin, UpdateAdminView)

修改页面

xadmin.site.register_plugin(UeditorPlugin, CreateAdminView)

### 6、字段显示样式

courses/adminx.py文件:

class CourseAdmin(object):

# 字段显示样式
style_fields = {"detail": "ueditor"}
### 7、注册进入plugins
找到plugins文件夹下的__init__.py文件,在PLUGINS中写入 

PLUGINS= ('ueditor',)

就是这样:![](https://upload-images.jianshu.io/upload_images/8964398-9f83eb8f6ee980af.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

然后运行一下我们的项目,登录到xadmin后台查看一下,富文本出来:
![](https://upload-images.jianshu.io/upload_images/8964398-34540482f02c3dda.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
接着在前端刷新一下页面,如果没有出现:
![](https://upload-images.jianshu.io/upload_images/8964398-e930ce38bb41ca76.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
那可能是你的course-detail.html页面中设置的有问题:
![](https://upload-images.jianshu.io/upload_images/8964398-2429c372ce0499cb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
弄好以后,页面还是现实元原始的html代码,这是不允许的,所以我们需要进一步配置:在course-detail.html页面中,关闭转义功能:

{% autoescape off %}

{{ course.detail }}

{% endautoescape %}

现在重新刷新一下我们的页面:

至此,本篇关于xadmin进阶开发的介绍就到此为止了,感谢你的赏阅!

本篇笔记对应于第二十六篇代码,对应于github的位置是https://github.com/licheetools/eduline

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏从零开始学 Web 前端

从零开始学 Web 之 Vue.js(四)Vue的Ajax请求和跨域

在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目。现在就让我们一起进入 Web 前端学习的冒险之旅吧!

2782
来自专栏韩东吉的Unity杂货铺

零基础入门 37:加强版日志窗口

又是俩星期不见,大家好,刚刚忙完,所以现在深夜更新,今天的主题描述我用语音和大家来介绍。

1201
来自专栏python爬虫实战之路

网络字体反爬之起点中文小说

前几天跟同事聊到最近在看什么小说,想起之前看过一篇文章说的是网络十大水文,就想把起点上的小说信息爬一下,搞点可视化数据看看。这段时间正在看爬虫框架-pyspid...

2092
来自专栏lgp20151222

tar包和jar包和war包的区别?

tar:tar是*nix下的打包工具,生成的包通常也用tar作为扩展名,其实tar只是负责打包,不一定有压缩,事实上可以压缩,也可以不压缩,通常你看到xxxx....

1152
来自专栏前端架构与工程

boi剖析 - 基于webpack的css sprites实现方案

本文是58到家前端工程化集成解决方案boi的博文系列之一。boi是基于webpack打造的一站式前端工程化解决方案,现已开源Github。 作为前端构建工具不...

3349
来自专栏用户2442861的专栏

linux之ldconfig工具的使用

ldconfig是一个动态链接库管理命令 为了让动态链接库为系统所共享,还需运行动态链接库的管理命令--ldconfig ldconfig  命令的用途...

881
来自专栏机器学习和数学

[编程经验] Python中使用selenium进行动态爬虫

Hello,大家好!停更了这么久,中间发生了很多事情,我的心情也发生了很大的变化,看着每天在增长的粉丝,实在不想就这么放弃了,所以以后我会尽量保持在一周一篇的进...

1892
来自专栏软件测试经验与教训

XSS漏洞总结

同源策略 影响源的因素:host,子域名,端口,协议 a.com通过以下代码:

4933
来自专栏云飞学编程

python简单应用!用爬虫来采集天猫所有优惠券信息,写入本地文件

随便找一段文字,然后点击右键查看网页源代码,看看是否存在该文字,如果存在,那么这个网页就是静态网站了!很幸运,这个网站居然是静态的。

1292
来自专栏软件开发

Node.js开发Web后台服务

一、简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/...

1.5K9

扫码关注云+社区

领取腾讯云代金券