Django+Xadmin打造在线教育系统(一)
系统概括:
- 系统具有完整的用户登录注册以及找回密码功能,拥有完整个人中心。
- 个人中心: 修改头像,修改密码,修改邮箱,可以看到我的课程以及我的收藏。可以删除收藏,我的消息。
- 导航栏: 公开课,授课讲师,授课机构,全局搜索。
- 点击公开课–> 课程列表,排序-搜索。热门课程推荐,课程的分页。
- 点击课程–> 课程详情页中对课程进行收藏,取消收藏。富文本展示课程内容。
- 点击开始学习–> 课程的章节信息,课程的评论信息。课程资源的下载链接。
- 点击授课讲师–>授课讲师列表页,对讲师进行人气排序以及分页,右边有讲师排行榜。
- 点击讲师的详情页面–> 对讲师进行收藏和分享,以及讲师的全部课程。
- 导航栏: 授课机构有分页,排序筛选功能。
- 机构列表页右侧有快速提交我要学习的表单。
- 点击机构–> 左侧:机构首页,机构课程,机构介绍,机构讲师。
- 后台管理系统可以切换主题。左侧每一个功能都有列表显示, 增删改查,筛选功能。
- 课程列表页可以对不同字段进行排序。选择多条记录进行删除操作。
- 课程列表页:过滤器->选择字段范围等,搜索,导出csv,xml,json。
- 课程新增页面上传图片,富文本的编辑。时间选择,添加章节,添加课程资源。
- 日志记录:记录后台人员的操作
环境
python == 3.6
django == 2.0
创建工程
django-admin startproject MxOnline
配置settings.py文件
# 数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'imooc', #数据库名字
'USER': 'root', #账号
'PASSWORD': '123456', #密码
'HOST': '127.0.0.1', #IP
'PORT': '3306', #端口
}
}
# 使用中文
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
# 静态文件路径(须在根目录下创建static目录)
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
数据库设计
创建四个app,并将其添加到 INSTALLED_APPS中
python manage.py startapp users
python manage.py startapp course
python manage.py startapp organization
python manage.py startapp operation
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users',
'course',
'operation',
'organization',
]
在根目录下新建一个apps文件夹,将创建的四个app文件拖到apps文件夹下,大致结构

将apps目录添加到项目路径中
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,os.path.join(BASE_DIR,'apps'))
重载UserProfile
# 使用自己写的UserProfile,而不是系统的
AUTH_USER_MODEL = 'users.UserProfile'
users modesl.py设计
from datetime import datetime
from django.contrib.auth.models import AbstractUser
from django.db import models
class UserProfile(AbstractUser):
# 自定义的性别选择规则
GENDER_CHOICES = (
("male", u"男"),
("female", u"女")
)
# 昵称
nick_name = models.CharField(max_length=50, verbose_name=u"昵称", default="")
# 生日,可以为空
birthday = models.DateField(verbose_name=u"生日", null=True, blank=True)
# 性别 只能男或女,默认女
gender = models.CharField(
max_length=6,
verbose_name=u"性别",
choices=GENDER_CHOICES,
default="female")
# 地址
address = models.CharField(max_length=100, verbose_name="地址", default="")
# 电话
mobile = models.CharField(max_length=11, null=True, blank=True)
# 头像 默认使用default.png
image = models.ImageField(
upload_to="image/%Y/%m",
default=u"image/default.png",
max_length=100
)
# meta信息,即后台栏目名
class Meta:
verbose_name = "用户信息"
verbose_name_plural = verbose_name
# 重载str方法,打印实例会打印username,username为继承自abstractuser
def __str__(self):
return self.username
# 邮箱验证码model
class EmailVerifyRecord(models.Model):
SEND_CHOICES = (
("register", u"注册"),
("forget", u"找回密码")
)
code = models.CharField(max_length=20, verbose_name=u"验证码")
# 未设置null = true blank = true 默认不可为空
email = models.EmailField(max_length=50, verbose_name=u"邮箱")
send_type = models.CharField(choices=SEND_CHOICES, max_length=10)
# 这里的now得去掉(),不去掉会根据编译时间。而不是根据实例化时间。
send_time = models.DateTimeField(default=datetime.now)
class Meta:
verbose_name = "邮箱验证码"
verbose_name_plural = verbose_name
# 轮播图model
class Banner(models.Model):
title = models.CharField(max_length=100, verbose_name=u"标题")
image = models.ImageField(
upload_to="banner/%Y/%m",
verbose_name=u"轮播图",
max_length=100)
url = models.URLField(max_length=200, verbose_name=u"访问地址")
# 默认index很大靠后。想要靠前修改index值。
index = models.IntegerField(default=100, verbose_name=u"顺序")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = u"轮播图"
verbose_name_plural = verbose_name
course models.py编写
from datetime import datetime
# 课程信息表
from django.db import models
class Course(models.Model):
DEGREE_CHOICES = (
("cj", u"初级"),
("zj", u"中级"),
("gj", u"高级")
)
name = models.CharField(max_length=50, verbose_name=u"课程名")
desc = models.CharField(max_length=300, verbose_name=u"课程描述")
# TextField允许我们不输入长度。可以输入到无限大。暂时定义为TextFiled,之后更新为富文本
detail = models.TextField(verbose_name=u"课程详情")
degree = models.CharField(choices=DEGREE_CHOICES, max_length=2)
# 使用分钟做后台记录(存储最小单位)前台转换
learn_times = models.IntegerField(default=0, verbose_name=u"学习时长(分钟数)")
# 保存学习人数:点击开始学习才算
students = models.IntegerField(default=0, verbose_name=u"学习人数")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏人数")
image = models.ImageField(
upload_to="courses/%Y/%m",
verbose_name=u"封面图",
max_length=100)
# 保存点击量,点进页面就算
click_nums = 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
# 章节
class Lesson(models.Model):
# 因为一个课程对应很多章节。所以在章节表中将课程设置为外键。
# 作为一个字段来让我们可以知道这个章节对应那个课程
course = models.ForeignKey(Course, verbose_name=u"课程", on_delete=models.CASCADE)
name = models.CharField(max_length=100, verbose_name=u"章节名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = u"章节"
verbose_name_plural = verbose_name
# 每章视频
class Video(models.Model):
# 因为一个章节对应很多视频。所以在视频表中将章节设置为外键。
# 作为一个字段来存储让我们可以知道这个视频对应哪个章节.
lesson = models.ForeignKey(Lesson, verbose_name=u"章节", on_delete=models.CASCADE)
name = models.CharField(max_length=100, verbose_name=u"视频名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = u"视频"
verbose_name_plural = verbose_name
# 课程资源
class CourseResource(models.Model):
# 因为一个课程对应很多资源。所以在课程资源表中将课程设置为外键。
# 作为一个字段来让我们可以知道这个资源对应那个课程
course = models.ForeignKey(Course, verbose_name=u"课程", on_delete=models.CASCADE)
name = models.CharField(max_length=100, verbose_name=u"名称")
# 这里定义成文件类型的field,后台管理系统中会直接有上传的按钮。
# FileField也是一个字符串类型,要指定最大长度。
download = models.FileField(
upload_to="course/resource/%Y/%m",
verbose_name=u"资源文件",
max_length=100)
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = u"课程资源"
verbose_name_plural = verbose_name
organization modesl.py设计
from datetime import datetime
from django.db import models
# Create your models here.
# 城市字典
class CityDict(models.Model):
name = models.CharField(max_length=20, verbose_name=u"城市")
# 城市描述:备用不一定展示出来
desc = models.CharField(max_length=200, verbose_name=u"描述")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = u"城市"
verbose_name_plural = verbose_name
# 课程机构
class CourseOrg(models.Model):
name = models.CharField(max_length=50, verbose_name=u"机构名称")
# 机构描述,后面会替换为富文本展示
desc = models.TextField(verbose_name=u"机构描述")
click_nums = models.IntegerField(default=0, verbose_name=u"点击数")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏数")
image = models.ImageField(
upload_to="org/%Y/%m",
verbose_name=u"封面图",
max_length=100)
address = models.CharField(max_length=150, verbose_name=u"机构地址")
# 一个城市可以有很多课程机构,通过将city设置外键,变成课程机构的一个字段
# 可以让我们通过机构找到城市
city = models.ForeignKey(CityDict, verbose_name=u"所在城市", on_delete=models.CASCADE)
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = u"课程机构"
verbose_name_plural = verbose_name
# 讲师
class Teacher(models.Model):
# 一个机构会有很多老师,所以我们在讲师表添加外键并把课程机构名称保存下来
# 可以使我们通过讲师找到对应的机构
org = models.ForeignKey(CourseOrg, verbose_name=u"所属机构", on_delete=models.CASCADE)
name = models.CharField(max_length=50, verbose_name=u"教师名称")
work_years = models.IntegerField(default=0, verbose_name=u"工作年限")
work_company = models.CharField(max_length=50, verbose_name=u"就职公司")
work_position = models.CharField(max_length=50, verbose_name=u"公司职位")
points = models.CharField(max_length=50, verbose_name=u"教学特点")
click_nums = models.IntegerField(default=0, verbose_name=u"点击数")
fav_nums = 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
operation models.py设计
from datetime import datetime
# 引入我们CourseComments所需要的外键models
from django.db import models
from users.models import UserProfile
from course.models import Course
# 用户我要学习表单
class UserAsk(models.Model):
name = models.CharField(max_length=20, verbose_name=u"姓名")
mobile = models.CharField(max_length=11, verbose_name=u"手机")
course_name = models.CharField(max_length=50, verbose_name=u"课程名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = u"用户咨询"
verbose_name_plural = verbose_name
# 用户对于课程评论
class CourseComments(models.Model):
# 会涉及两个外键: 1. 用户, 2. 课程。import进来
course = models.ForeignKey(Course, verbose_name=u"课程", on_delete=models.CASCADE)
user = models.ForeignKey(UserProfile, verbose_name=u"用户", on_delete=models.CASCADE)
comments = models.CharField(max_length=250, verbose_name=u"评论")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"评论时间")
class Meta:
verbose_name = u"课程评论"
verbose_name_plural = verbose_name
# 用户对于课程,机构,讲师的收藏
class UserFavorite(models.Model):
# 会涉及四个外键。用户,课程,机构,讲师import
TYPE_CHOICES = (
(1, u"课程"),
(2, u"课程机构"),
(3, u"讲师")
)
user = models.ForeignKey(UserProfile, verbose_name=u"用户", on_delete=models.CASCADE)
# course = models.ForeignKey(Course, verbose_name=u"课程")
# teacher = models.ForeignKey()
# org = models.ForeignKey()
# fav_type =
# 机智版
# 直接保存用户的id.
fav_id = models.IntegerField(default=0)
# 表明收藏的是哪种类型。
fav_type = models.IntegerField(
choices=TYPE_CHOICES,
default=1,
verbose_name=u"收藏类型")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"评论时间")
class Meta:
verbose_name = u"用户收藏"
verbose_name_plural = verbose_name
# 用户消息表
class UserMessage(models.Model):
# 因为我们的消息有两种:发给全员和发给某一个用户。
# 所以如果使用外键,每个消息会对应要有用户。很难实现全员消息。
# 机智版 为0发给所有用户,不为0就是发给用户的id
user = models.IntegerField(default=0, verbose_name=u"接收用户")
message = models.CharField(max_length=500, verbose_name=u"消息内容")
# 是否已读: 布尔类型 BooleanField False未读,True表示已读
has_read = models.BooleanField(default=False, verbose_name=u"是否已读")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = u"用户消息"
verbose_name_plural = verbose_name
# 用户课程表
class UserCourse(models.Model):
# 会涉及两个外键: 1. 用户, 2. 课程。import进来
course = models.ForeignKey(Course, verbose_name=u"课程", on_delete=models.CASCADE)
user = models.ForeignKey(UserProfile, verbose_name=u"用户", on_delete=models.CASCADE)
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
class Meta:
verbose_name = u"用户课程"
verbose_name_plural = verbose_name
将models映射到数据库中
python manage.py makemigrations
python manage.py migrate
Django+Xadmin打造在线教育系统(一)的更多相关文章
- Django+Xadmin打造在线教育系统(四)
完成授课机构的功能 模板继承 在templates目录下,新建base.html,剪切org-list.html内容到里面 编写org-list.html内容 继承base.html,将里面的面包屑和 ...
- Django+Xadmin打造在线教育系统(三)
完成登录 注册 找回密码 激活 验证码集成 将HTML文件拷贝到templates目录下,css,js,img,media,images文件夹拷贝到static文件夹下 修改index.html和lo ...
- Django+Xadmin打造在线教育系统(二)
基于xadmin的后台管理 先使用pip进行安装xadmin及其依赖包 pip install django-adminx 安装完成后卸载xadmin,保留依赖包即可 pip uninstall dj ...
- Django+Xadmin打造在线教育系统(九)
xadmin的进阶开发 因版本问题.有些配置可能无效 自定义icon xadmin的图标采用的是第三方css样式font awesome,我们可以进官网下载最新的样式替代原本的,下载地址:http:/ ...
- Django+Xadmin打造在线教育系统(七)
全局导航&个人中心&全局搜索 配置全局导航 让index页面也继承base页面,注意首页有个单独的__index.js__ base页面的导航栏也进行配置 <nav> &l ...
- Django+Xadmin打造在线教育系统(八)
首页和全局404,500配置 轮播图 公开课 授课机构 新建view ## 首页view class IndexView(View): def get(self,request): # 取出轮播图 a ...
- Django+Xadmin打造在线教育系统(五)
课程相关功能实现 课程列表 创建课程相关的urls.py path("course/", include('course.urls', namespace="course ...
- Django+Xadmin打造在线教育系统(六)
讲师相关功能实现 拷贝并修改teacher-list.html和teacher-detail.html, 继承base模板 # 讲师列表 path('teacher_list/', TeacherLi ...
- Django+xadmin打造在线教育平台(一)
目录 在线教育平台(一) 在线教育平台(二) 在线教育平台(三) 在线教育平台(四) 在线教育平台(五) 在线教育平台(六) 在线教育平台(七) 在线教育平台( ...
随机推荐
- ab 压力测试
两个 Time per request ab有一个-c n参数,就是第一行的Concurrency Level,可以让ab创建n个并发连接进行测试. 第一个Time per request 代表每个链 ...
- for 循环 以及基本的数据类型
for 循环: for 关键字 i 变量(此处可以更改 更改规则参考变量命名规则) in 关键字 可迭代对象 (想要循环谁就放谁,注意:数字除外 因为数字不可迭代) for 循环内可以进行任意操作,可 ...
- Appium-实现手势密码登陆
前言: 前几天有人问我,手势登陆如何做?于是我找了一个APP试了试,所以本文来总结使用Python+Appium来实现手势密码登陆APP. 环境: MacOS:10.13.4 Appium-deskt ...
- Python-正则复习-56
# 正则表达式# 字符组 [字符]# 元字符 # \w \d \s # \W \D \S # . 除了换行符以外的任意字符 # \n \t # \b # ^ $ 匹配字符串的开始和结束 # () 分组 ...
- A+B大数运算
基础加法大数运算: [https://vjudge.net/problem/HDU-1002] 题目: 输入两个长度不超过1000的整数求出sum. 思路: 由于数字很大不能直接加,用字符串形式输入, ...
- (Beta)团队贡献分
Beta阶段团队每个成员都积极响应一起完成了开发, 所以最后我们一致决定各个成员的贡献分相同. 林珣玙 53 康家华 52 张启东 51 刘彦熙 49 马瑶华 48 仇栋民 47
- Day3 Python基础之while、for循环(二)
1.数据运算 算数运算 整除运算:// 取余运算:% 指数运算:** 赋值运算 b+=a;等价于b=b+a 比较运算 >,<,==,!=,>=,<= 逻辑运算符 and .or ...
- Vue基本使用和指令集
Vue的使用 一.安装 对于新手来说,强烈建议大家使用<script>引入: 二. 引入vue.js文件 我们能发现,引入vue.js文件之后,Vue被注册为一个全局的变量,它是一个构造函 ...
- IdentityServer4【QuickStart】之利用OpenID Connect添加用户认证
利用OpenID Connect添加用户认证 利用OpenID Connect添加用户认证 在这个示例中我们想要通过OpenID Connect协议将交互用户添加到我们的IdentityServer上 ...
- 对于vue和react“页面间”传递数据的理解误区
前言 如果我们想要实现多个标签页之间的通信,可以使用localStorage.cookie等,但是能不能用vue或react呢? 结论 答案是NO,因为vue和react虽然可以在“多个”页面之间传递 ...