因版本问题.有些配置可能无效javascript
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去实现这一功能git
class LessonInline(object): model = Lesson extra = 0 class CourseResourceInline(object): model = CourseResource extra = 0 # 在CourseAdmin中使用inlines添加上面两个的方法 class CourseAdmin(object): inlines = [LessonInline,CourseResourceInline] #增长章节和课程资源
课程里面分为轮播课程和不是轮播课程两种类型,咱们能够分开来管理
在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)
能够在列表上快速修改内容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()
下载地址 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 }}
新建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">×</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)