美文网首页
Django+Xadmin打造在线教育系统(九)

Django+Xadmin打造在线教育系统(九)

作者: 听你讲故事啊 | 来源:发表于2018-09-17 20:40 被阅读0次

    xadmin的进阶开发

    因版本问题.有些配置可能无效

    自定义icon

    xadmin的图标采用的是第三方css样式font awesome,我们可以进官网下载最新的样式替代原本的,下载地址:http://www.fontawesome.com.cn/

    下载完后把里面的“css”和“fonts”两个文件夹拷贝到xadmin的源码(路径:xadmin/static/vendor/font-awesome)里面
    使用model_icon来进行修改

    # Course的admin管理器
    class CourseAdmin(object):
        '''课程'''
    
        list_display = [ 'name','desc','detail','degree','learn_times','students']
        search_fields = ['name', 'desc', 'detail', 'degree', 'students']
        list_filter = [ 'name','desc','detail','degree','learn_times','students']
        model_icon = 'fa fa-book'
    

    默认排序、只读字段和不显示的字段

    课程:

    • 按点击数倒序排序
    • 点击数不能编辑
    • 不显示收藏人数
    # Course的admin管理器
    class CourseAdmin(object):
        '''课程'''
    
        list_display = [ 'name','desc','detail','degree','learn_times','students']   #显示的字段
        search_fields = ['name', 'desc', 'detail', 'degree', 'students']             #搜索
        list_filter = [ 'name','desc','detail','degree','learn_times','students']    #过滤 
        model_icon = 'fa fa-book'            #图标
        ordering = ['-click_nums']           #排序
        readonly_fields = ['click_nums']     #只读字段,不能编辑
        exclude = ['fav_nums']               #不显示的字段
    

    下拉框搜索

    写在外键所指的adminx配置中

    relfield_style = 'fk-ajax'
    

    当有外键指向他,会以ajax方式加载
    数据量过大时很有用

    inlines添加数据

    目前在添加课程的时候没法添加章节和课程资源,我们可以用inlines去实现这一功能

    class LessonInline(object):
        model = Lesson
        extra = 0
    
    
    class CourseResourceInline(object):
        model = CourseResource
        extra = 0
    
    
    # 在CourseAdmin中使用inlines添加上面两个的方法
    class CourseAdmin(object):
        inlines = [LessonInline,CourseResourceInline]    #增加章节和课程资源
    

    一张表分两个Model来管理

    课程里面分为轮播课程和不是轮播课程两种类型,我们可以分开来管理
    course/models.py里面新建一个Model

    class BannerCourse(Course):
        '''显示轮播课程'''
        class Meta:
            verbose_name = '轮播课程'
            verbose_name_plural = verbose_name
            #这里必须设置proxy=True,这样就不会再生成一张表,同时还具有Model的功能
            proxy = True
    

    course/adminx.py

    class CourseAdmin(object):
        '''课程'''
    
        list_display = [ 'name','desc','detail','degree','learn_times','students']   #显示的字段
        search_fields = ['name', 'desc', 'detail', 'degree', 'students']             #搜索
        list_filter = [ 'name','desc','detail','degree','learn_times','students']    #过滤
        model_icon = 'fa fa-book'            #图标
        ordering = ['-click_nums']           #排序
        readonly_fields = ['click_nums']     #只读字段
        exclude = ['fav_nums']               #不显示的字段
        inlines = [LessonInline,CourseResourceInline]    #增加章节和课程资源
    
        def queryset(self):
            # 重载queryset方法,来过滤出我们想要的数据的
            qs = super(CourseAdmin, self).queryset()
            # 只显示is_banner=True的课程
            qs = qs.filter(is_banner=False)
            return qs
    
    
    class BannerCourseAdmin(object):
        '''轮播课程'''
    
        list_display = [ 'name','desc','detail','degree','learn_times','students']
        search_fields = ['name', 'desc', 'detail', 'degree', 'students']
        list_filter = [ 'name','desc','detail','degree','learn_times','students']
        model_icon = 'fa fa-book'
        ordering = ['-click_nums']
        readonly_fields = ['click_nums']
        exclude = ['fav_nums']
        inlines = [LessonInline,CourseResourceInline]
    
        def queryset(self):
            #重载queryset方法,来过滤出我们想要的数据的
            qs = super(BannerCourseAdmin, self).queryset()
            #只显示is_banner=True的课程
            qs = qs.filter(is_banner=True)
            return qs
    
    # 将管理器与model进行注册关联
    xadmin.site.register(Course, CourseAdmin)
    xadmin.site.register(BannerCourse, BannerCourseAdmin)
    

    xadmin的其它常见功能

    可以在列表上快速修改内容

    list_editable = [ 'degree','desc']
    

    自定义函数作为列

    def get_zj_nums(self):
        return self.lesson_set.all().count()
    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://iceflower.xyz'>跳转</>")
    go_to.short_description = "跳转"
    

    refresh定时刷新工具

    refresh_times = [3,5]           #自动刷新(里面是秒数)
    

    字段联动
    应用场景:当添加一门课程的时候,希望课程机构里面的课程数 +1
    重写xadmin的save_models方法

     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自行探究

    • local 语言包
    • migration 数据表的记录
    • plugins 每一个后台页面都是一个plugin 插件机制
    • static文件。js css
    • template xadmin自己用到的html文件
    • 对django admin的封装

    增加富文本编辑器Ueditor

    下载地址 https://github.com/twz915/DjangoUeditor3/
    解压后,把DjangoUeditor文件夹拷贝到项目目录下面

    # settings中添加app
    
    INSTALLED_APPS = [
        'DjangoUeditor',
    ]
    
     # 富文本编辑器url
        path('ueditor/',include('DjangoUeditor.urls' )),
    

    course/models.py中Course修改detail字段

    class Course(models.Model):
        # detail = models.TextField("课程详情")
        detail = UEditorField(verbose_name=u'课程详情', width=600, height=300, imagePath="courses/ueditor/",
                              filePath="courses/ueditor/", default='')
    

    xadmin/plugs目录下新建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
    
        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)
    

    xadmin/plugs/__init__.py里面添加ueditor插件

    PLUGINS = (
       'ueditor',
    )
    

    course/adminx.py中使用

    class CourseAdmin(object):
        #detail就是要显示为富文本的字段名
        style_fields = {"detail": "ueditor"}
    

    在模板中必须关闭Django的自动转义才能正常显示

        <div class="tab_cont tab_cont1">
             {% autoescape off %}
             {{ course.detail }}
             {% endautoescape %}
         </div>
    

    或者

        {{ course.detail|safe }}
    

    导入excel

    • 如何注入导入excel代码到菜单
    • 如何只在课程列表显示
    • 如何接收文件对文件进行处理

    新建xadmin/plugins/excel.py

    import xadmin
    from xadmin.views import BaseAdminPlugin, ListAdminView
    from django.template import loader
    
    
    #excel 导入
    class ListImportExcelPlugin(BaseAdminPlugin):
        import_excel = False
    
        def init_request(self, *args, **kwargs):
            return bool(self.import_excel)
    
        def block_top_toolbar(self, context, nodes):
            nodes.append(loader.render_to_string('xadmin/excel/model_list.top_toolbar.import.html', context=get_context_dict(context)))
    
    
    xadmin.site.register_plugin(ListImportExcelPlugin, ListAdminView)
    

    添加到init.py文件中

    PLUGINS = (
       'excel',
    )
    

    新建xadmin/templates/xadmin/excel/model_list.top_toolbar.import.html

        {% load i18n %}
        <div class="btn-group export">
          <a class="dropdown-toggle btn btn-default btn-sm" data-toggle="dropdown" href="#">
            <i class="icon-share"></i> 导入 <span class="caret"></span>
          </a>
          <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
              <li><a data-toggle="modal" data-target="#export-modal-import-excel"><i class="icon-circle-arrow-down"></i> 导入 Excel</a></li>
          </ul>
            <script>
                function fileChange(target){
        //检测上传文件的类型
                    var imgName = document.all.submit_upload.value;
                    var ext,idx;
                    if (imgName == ''){
                        document.all.submit_upload_b.disabled=true;
                        alert("请选择需要上传的 xls 文件!");
                        return;
                    } else {
                        idx = imgName.lastIndexOf(".");
                        if (idx != -1){
                            ext = imgName.substr(idx+1).toUpperCase();
                            ext = ext.toLowerCase( );
        {#                    alert("ext="+ext);#}
                            if (ext != 'xls' && ext != 'xlsx'){
                                document.all.submit_upload_b.disabled=true;
                                alert("只能上传 .xls 类型的文件!");
    
                                return;
                            }
                        } else {
                            document.all.submit_upload_b.disabled=true;
                            alert("只能上传 .xls 类型的文件!");
                            return;
                        }
                    }
    
                }
            </script>
            <div id="export-modal-import-excel" class="modal fade">
              <div class="modal-dialog">
                <div class="modal-content">
                  <form method="post" action="" enctype="multipart/form-data">
                      {% csrf_token %}
                  <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                    <h4 class="modal-title">导入 Excel</h4>
                  </div>
                  <div class="modal-body">
                       <input type="file" onchange="fileChange(this)" name="excel" id="submit_upload">
    
                  </div>
                  <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
                    <button class="btn btn-success" type="submit" id="submit_upload_b"><i class="icon-share"></i> 导入</button>
                  </div>
                  </form>
                </div><!-- /.modal-content -->
              </div><!-- /.modal-dalog -->
            </div><!-- /.modal -->
    
        </div>
    

    只需要在adminx中设置变量import_excel=True就可以开启导入按钮
    在adminx中重写post方法,将文件内容保存到数据中

    def post(self, request, *args , **kwargs):
        if 'excel' in request.FILES:
            pass
    
    # 中间pass步骤不管做什么事情,都要最后return父类的
    
    return super(CourseAdmin, self).post(request, args, kwargs)
    

    相关文章

      网友评论

          本文标题:Django+Xadmin打造在线教育系统(九)

          本文链接:https://www.haomeiwen.com/subject/hxpdnftx.html