第十一章 在线教育平台(xadmin的进阶开发)

xadmin的进阶开发

标签: django


userprofile 注册以及django的权限管理

  • 用户信息放入用户栏中(针对老版本的bug)

通过将userprofile继承与xadmin中plugin下面的UserAdmin ,并注册userprofile,同时注销User。

# _*_ encoding:utf-8 _*_

__author__ = 'wrj008'
__date__ = '2018/3/9 17:15'

import xadmin
from xadmin import views
from xadmin.plugins.auth import UserAdmin, User
from .models import EmailVerifyRecord, Banner

from users.models import UserProfile


class UserProfileAdmin(UserAdmin):
    pass


class BaseSetting(object):
    enable_themes = True
    use_bootswatch = True


class GloableSetting(object):
    site_title = '教育后台管理系统'
    site_footer = 'xiaojinzi'
    menu_style = 'accordion'


class EmailVerifyRecordAdmin(object):
    list_display = ['code', 'email', 'send_time', 'send_type']
    search_fields = ['code', 'email', 'send_time']
    list_filter = ['code', 'email', 'send_time', 'send_type']


class BannerAdmin(object):
    list_display = ['title', 'image', 'url', 'index', 'add_time']
    search_fields = ['title', 'image', 'url', 'index']
    list_filter = ['title', 'image', 'url', 'index', 'add_time']


xadmin.site.unregister(User)
xadmin.site.register(EmailVerifyRecord, EmailVerifyRecordAdmin)
xadmin.site.register(Banner, BannerAdmin)
xadmin.site.register(UserProfile, UserProfileAdmin)
xadmin.site.register(views.BaseAdminView, BaseSetting)
xadmin.site.register(views.CommAdminView, GloableSetting)

  • 另一种方式是通过在xadmin.auth中添加
from django.contrib.auth import get_user_model
User = get_user_model()
  • 用户的权限管理

通过对软件进行操作。

用户后台界面中的icon图片进行修改

django用的是font-awesome样式风格。 地址

在修改的adminx的下面添加
model_icon = 'fa fa-circle-o-notch fa-spin'
排序
ordering = ['-click_nums']
只读字段显示
readonly_fields = ['click_nums']
不显示字段(与上面会存在冲突)
exclude = ['']
下拉选择过多时,通过外键的主表添加字段,异步搜索呈现内容
relfield_style = 'fk-ajax'
列表中字段直接修改
list_editable = ['']

自定义列表返回数据,同一model两个注册管理器

  • inline操作

添加课程的同时在课程截界面添加章节信息。

class LessonAinline(object):
    model = Lesson
    extra = 0


class CourseAdmin(object):
    list_display = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                    'add_time']
    search_fields = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image']
    list_filter = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                   'add_time']
    inlines = [LessonAinline]

  • 同一model两个注册管理器

例如其中的轮播课程,可以分为两个列表页,其中一个是轮播课程界面,另一个是非轮播界面。

class BannerCourse(Course):
    """
    轮播图课程
    """
    class Meta:
        verbose_name = u'轮播图课程'
        verbose_name_plural = verbose_name
        proxy = True
# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals
from datetime import datetime
from django.db import models

from organization.models import CourseOrg, Teacher

# Create your models here.


class Course(models.Model):
    course_org = models.ForeignKey(CourseOrg, verbose_name=u'课程机构')
    name = models.CharField(max_length=128, verbose_name=u'课程名称')
    desc = models.CharField(max_length=256, verbose_name=u'课程描述')
    category = models.CharField(default=u'后端开发', max_length=20, verbose_name=u'课程分类')
    detail = models.TextField(verbose_name=u'课程详情')
    degree = models.CharField(choices=(('cj', '初级'), ('zj', '中级'), ('gj', '高级')), max_length=2, verbose_name=u'课程难度')
    learn_time = models.IntegerField(default=0, verbose_name=u'课程时长')
    students = models.IntegerField(default=0, verbose_name=u'学习人数')
    fav_nums = models.IntegerField(default=0, verbose_name=u'收藏人数')
    click_nums = models.IntegerField(default=0, verbose_name=u'点击数')
    teacher = models.ForeignKey(Teacher, null=True, blank=True, verbose_name=u'教师外键')
    image = models.ImageField(upload_to='courses/%Y/%m', verbose_name=u'封面图', max_length=128)
    tag = models.CharField(default='', max_length=20, verbose_name=u'课程标签')
    youneed_know = models.CharField(default='', max_length=256, verbose_name=u'课程须知')
    is_banner = models.BooleanField(default=False, verbose_name=u'是否是广告栏')
    teacher_tell = models.CharField(default='', max_length=256, verbose_name=u'教师建议')
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')

    class Meta:
        verbose_name = u'课程信息'
        verbose_name_plural = verbose_name

    def get_lesson_count(self):
        # 课程章节外键获取总数
        return self.lesson_set.all().count()

    def get_students_list(self):
        # 根据用户操作外键获取学习用户
        return self.usercourse_set.all()[:5]

    def ger_lesson_detail(self):
        # 获取所有的章节信息
        return self.lesson_set.all()

    def __unicode__(self):
        return self.name


class BannerCourse(Course):
    """
    轮播图课程
    """
    class Meta:
        verbose_name = u'轮播图课程'
        verbose_name_plural = verbose_name
        proxy = True


class Lesson(models.Model):
    course = models.ForeignKey(Course, verbose_name=u'章节外键')
    name = models.CharField(max_length=128, verbose_name=u'章节名称')
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')

    class Meta:
        verbose_name = u'章节信息'
        verbose_name_plural = verbose_name

    def __unicode__(self):
        return self.name

    def get_video_info(self):
        # 获取所有视屏信息
        return self.video_set.all()


class Video(models.Model):
    lesson = models.ForeignKey(Lesson, verbose_name=u'视频')
    name = models.CharField(max_length=128, verbose_name=u'视频名称')
    url = models.CharField(default='', max_length=200, verbose_name=u'章节连接')
    learn_time = models.IntegerField(default=0, verbose_name=u'章节时长')
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')

    class Meta:
        verbose_name = u'视频信息'
        verbose_name_plural = verbose_name

    def __unicode__(self):
        return self.name


class CourseResource(models.Model):
    course = models.ForeignKey(Course, verbose_name=u'资源')
    download = models.FileField(upload_to='course/resource/%Y/%m', verbose_name=u'下载地址', max_length=128)
    name = models.CharField(max_length=128, verbose_name=u'资源名称')
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')

    class Meta:
        verbose_name = u'资源信息'
        verbose_name_plural = verbose_name

# _*_ encoding:utf-8 _*_

__author__ = 'wrj008'
__date__ = '2018/3/10 8:49'

import xadmin
from .models import Course, Lesson, Video, CourseResource, BannerCourse


class LessonAinline(object):
    model = Lesson
    extra = 0


class CourseAdmin(object):
    list_display = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                    'add_time']
    search_fields = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image']
    list_filter = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                   'add_time']
    inlines = [LessonAinline]

    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_time', 'students', 'fav_nums', 'click_nums', 'image',
                    'add_time']
    search_fields = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image']
    list_filter = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                   'add_time']
    inlines = [LessonAinline]

    def queryset(self):
        qs = super(BannerCourseAdmin, self).queryset()
        qs = qs.filter(is_banner=True)
        return qs


class LessonAdmin(object):
    list_display = ['course', 'name', 'add_time']
    search_fields = ['course', 'name']
    list_filter = ['course', 'name', 'add_time']


class VideoAdmin(object):
    list_display = ['lesson', 'name', 'add_time']
    search_fields = ['lesson', 'name']
    list_filter = ['lesson', 'name', 'add_time']


class CourseResourceAdmin(object):
    list_display = ['course', 'download', 'name', 'add_time']
    search_fields = ['course', 'download', 'name']
    list_filter = ['course', 'download', 'name', 'add_time']


xadmin.site.register(Course, CourseAdmin)
xadmin.site.register(BannerCourse, BannerCourseAdmin)
xadmin.site.register(Lesson, LessonAdmin)
xadmin.site.register(Video, VideoAdmin)
xadmin.site.register(CourseResource, CourseResourceAdmin)

  • 函数显示
  def get_lesson_count(self):
        # 课程章节外键获取总数
        return self.lesson_set.all().count()

    get_lesson_count.short_description = '章节数'

    def go_to(self):
        from django.utils.safestring import mark_safe
        return mark_safe('<a href="www.baidu.com">跳转</a>')
        
    
  • 页面自动刷新
class CourseAdmin(object):
    list_display = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                    'add_time']
    search_fields = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image']
    list_filter = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                   'add_time']
    inlines = [LessonAinline]
    refresh_times = [3, 5]

    def queryset(self):
        qs = super(CourseAdmin, self).queryset()
        qs = qs.filter(is_banner=False)
        return qs
  • 课程保存,机构中课程数量更新
class CourseAdmin(object):
    list_display = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                    'add_time']
    search_fields = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image']
    list_filter = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                   'add_time']
    inlines = [LessonAinline]
    refresh_times = [3, 5]

    def queryset(self):
        qs = super(CourseAdmin, self).queryset()
        qs = qs.filter(is_banner=False)
        return qs

    def save_models(self):
        """
        课程保存机构课程数更新
        """
        obj = self.new_obj
        obj.save()
        if obj.course_org is not None:
            course_org = obj.course_org
            course_org.course_nums = Course.objects.filter(course_org=course_org).count()
            course_org.save()

富文本集成

富文本
某个字段使用某种样式
style_fields = {'detail': 'ueditor'}
  • django-ueditor 开源富文本文件插件功能开发

github 开源项目地址

1.进入文件目录
cd ****
workon '虚拟环境'
python setup.py install

2.如果1没效果,则采用源码放入本地第三方保重,和xadmin一个文件夹下

压缩包中的DjangoUeditor文件


注册
INSTALLED_APPS = [
    'DjangoUeditor',
]
配置url
 # richtext url
    url(r'^ueditor/', include('DjangoUeditor.urls'))
    
model字段进行变更
from DjangoUeditor.models import UEditorField 

    detail = UEditorField(verbose_name=u'课程详情', width=600, height=300, toolbars="full", imagePath="course/ueditor/", filePath="course/ueditor/", default='')

plugin插件变更

# _*_ encoding:utf-8 _*_

__author__ = 'wrj008'
__date__ = '2018/3/19 16:41'
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)

注册插件

将ueditor添加到plugin下的_init_中
PLUGINS = (
    ...
    'ueditor',
)

引用

class CourseAdmin(object):
    list_display = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                    'add_time']
    search_fields = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image']
    list_filter = ['name', 'desc', 'detail', 'degree', 'learn_time', 'students', 'fav_nums', 'click_nums', 'image',
                   'add_time']
    inlines = [LessonAinline]
    refresh_times = [3, 5]
    style_fields = {'detail': 'ueditor'}

    def queryset(self):
        qs = super(CourseAdmin, self).queryset()
        qs = qs.filter(is_banner=False)
        return qs

    def save_models(self):
        """
        课程保存机构课程数更新
        """
        obj = self.new_obj
        obj.save()
        if obj.course_org is not None:
            course_org = obj.course_org
            course_org.course_nums = Course.objects.filter(course_org=course_org).count()
            course_org.save()
详情页面展示
<div class="tab_cont tab_cont1">
    {% autoescape off %}
        {{ course.detail }}
    {% endautoescape %}

</div>

  • 本篇博客原视频博主[慕课在线教育平台]
  • 本篇博客撰写人: XiaoJinZi 转载请注明出处
  • 学生能力有限 附上邮箱: 986209501@qq.com 不足以及误处请大佬指责
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容