Django+Xadmin打造在線教育系統(九)

xadmin的進階開發

因版本問題.有些配置可能無效javascript

自定義icon

xadmin的圖標採用的是第三方css樣式font awesome,咱們能夠進官網下載最新的樣式替代本來的,下載地址:http://www.fontawesome.com.cn/css

下載完後把裏面的「css」和「fonts」兩個文件夾拷貝到xadmin的源碼(路徑:xadmin/static/vendor/font-awesome)裏面
使用model_icon來進行修改html

# 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'

默認排序、只讀字段和不顯示的字段

課程:java

  • 按點擊數倒序排序
  • 點擊數不能編輯
  • 不顯示收藏人數
# 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配置中node

relfield_style = 'fk-ajax'

當有外鍵指向他,會以ajax方式加載
數據量過大時頗有用python

inlines添加數據

目前在添加課程的時候無法添加章節和課程資源,咱們能夠用inlines去實現這一功能git

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裏面新建一個Modelgithub

class BannerCourse(Course):
    '''顯示輪播課程'''
    class Meta:
        verbose_name = '輪播課程'
        verbose_name_plural = verbose_name
        #這裏必須設置proxy=True,這樣就不會再生成一張表,同時還具備Model的功能
        proxy = True

course/adminx.pyajax

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的其它常見功能

能夠在列表上快速修改內容django

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)
相關文章
相關標籤/搜索