目录
代码
教程
学习自慕课网-使用python3.x与Django2.0.1开发的在线教育平台
一、前言
开发环境:
python: 3.6.4
Django: 2.0.2
后台管理:xadmin
1.1.项目介绍
系统概括:
- 系统具有完整的用户登录注册以及找回密码功能,拥有完整个人中心。
- 个人中心: 修改头像,修改密码,修改邮箱,可以看到我的课程以及我的收藏。可以删除收藏,我的消息。
- 导航栏: 公开课,授课讲师,授课机构,全局搜索。
- 点击
公开课
–> 课程列表,排序-搜索。热门课程推荐,课程的分页。 - 点击
课程
–> 课程详情页中对课程进行收藏,取消收藏。富文本展示课程内容。 - 点击
开始学习
–> 课程的章节信息,课程的评论信息。课程资源的下载链接。 - 点击
授课讲师
–>授课讲师列表页,对讲师进行人气排序以及分页,右边有讲师排行榜。 - 点击
讲师的详情页面
–> 对讲师进行收藏和分享,以及讲师的全部课程。 - 导航栏: 授课机构有分页,排序筛选功能。
- 机构列表页右侧有快速提交我要学习的表单。
- 点击
机构
–> 左侧:机构首页,机构课程,机构介绍,机构讲师。 - 后台管理系统可以
切换主题
。左侧每一个功能都有列表显示, 增删改查,筛选功能。 - 课程列表页可以对不同字段进行排序。选择多条记录进行删除操作。
- 课程列表页:过滤器->选择字段范围等,搜索,导出csv,xml,json。
- 课程新增页面上传图片,富文本的编辑。时间选择,添加章节,添加课程资源。
- 日志记录:记录后台人员的操作
1.2.创建工程
创建工程
django-admin startproject MxOnline
然后开始项目的开发
二、models设计
项目的开发都是从models设计开始,后台的管理和前端的渲染无非就是对数据库的增删改查,所以models设计的好坏对整个项目的开发起着至关重要的因素。
下面是我画的图,可以很直观的看出来我们需要的models。
放大显示:
创建四个app
python manage.py startapp users
python manage.py startapp course
python manage.py startapp organization
python manage.py startapp operation
然后分别设计每个app的models
2.1.users 用户
自定义userProfile
系统自动生成的user表如下:
- id: 主键, password 密码, last_login Django自动记录用户最后登录时间,。
- is_superuser 表明用户是否是超级用户(后台管理会用到)。
- username 用户名字段不要随便改动, email 邮箱,
- is_staff 表示是否是员工(后台管理会用到)。
- is_active 用户是否是激活状态, date_joined 注册时间。
个人中心页面信息:
users/models.py添加代码:
# users/models.py from django.db import models from django.contrib.auth.models import AbstractUser class UserProfile(AbstractUser): gender_choices = ( ('male','男'), ('female','女') ) nick_name = models.CharField('昵称',max_length=50,default='') birthday = models.DateField('生日',null=True,blank=True) gender = models.CharField('性别',max_length=10,choices=gender_choices,default='female') adress = models.CharField('地址',max_length=100,default='') mobile = models.CharField('手机号',max_length=11,null=True,blank=True) image = models.ImageField(upload_to='image/%Y%m',default='image/default.png',max_length=100) class Meta: verbose_name = '用户信息' verbose_name_plural = verbose_name def __str__(self): return self.username
然后做下面的一些设置
因为Image字段需要用到pillow
所以需要安装该库
pip install pillow
注册app
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'users' ]
重载AUTH_USER_MODEL
AUTH_USER_MODEL = 'users.UserProfile'
设计数据库为Mysql
# DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } # } DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mxonline', #数据库名字 'USER': 'root', #账号 'PASSWORD': '123456', #密码 'HOST': '127.0.0.1', #IP 'PORT': '3306', #端口 } }
init.py里面导入pymysql模块
# user/__init__.py import pymysql pymysql.install_as_MySQLdb()
迁移数据库
python manage.py makemigrations
python manage.py migrate
user中还需要添加的表(这些功能比较独立):
- EmailVerifyRecord - 邮箱验证码
- Banner - 轮播图
EmailVerifyRecord 验证码
代码如下:
class EmailVerifyRecord(models.Model): send_choices = ( ('register','注册'), ('forget','找回密码') ) code = models.CharField('验证码',max_length=20) email = models.EmailField('邮箱',max_length=50) send_type = models.CharField(choices=send_choices,max_length=10) send_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '邮箱验证码' verbose_name_plural = verbose_name
Banner 轮播图
代码如下:
class Banner(models.Model): title = models.CharField('标题',max_length=100) image = models.ImageField('轮播图',upload_to='banner/%Y%m',max_length=100) url = models.URLField('访问地址',max_length=200) index = models.IntegerField('顺序',default=100) add_time = models.DateTimeField('添加时间',default=datetime.now) class Meta: verbose_name = '轮播图' verbose_name_plural = verbose_name
说明:
image上传到哪里
url是图片的路径
index控制轮播图的播放顺序
这样users的三张表就创建完了
写代码要根据PEP8规范
每个class之间要空两格
2.2.Course 课程
课程app中需要四张表
- Course 课程表
- Lesson 章节信息
- Video 视频
- CourseResource 课程资源
(1)Course 课程表
代码如下:
from datetime import datetime from django.db import models class Course(models.Model): DEGREE_CHOICES = ( ("cj", "初级"), ("zj", "中级"), ("gj", "高级") ) name = models.CharField("课程名",max_length=50) desc = models.CharField("课程描述",max_length=300) detail = models.TextField("课程详情") degree = models.CharField('难度',choices=DEGREE_CHOICES, max_length=2) learn_times = models.IntegerField("学习时长(分钟数)",default=0) students = models.IntegerField("学习人数",default=0) fav_nums = models.IntegerField("收藏人数",default=0) image = models.ImageField("封面图",upload_to="courses/%Y/%m",max_length=100) click_nums = models.IntegerField("点击数",default=0) add_time = models.DateTimeField("添加时间",default=datetime.now,) class Meta: verbose_name = "课程" verbose_name_plural = verbose_name def __str__(self): return self.name
(2)Lesson 章节信息表
代码如下:
class Lesson(models.Model): course = models.ForeignKey(Course,verbose_name='课程',on_delete=models.CASCADE) name = models.CharField("章节名",max_length=100) add_time = models.DateTimeField("添加时间",default=datetime.now) class Meta: verbose_name = "章节" verbose_name_plural = verbose_name def __str__(self): return '《{0}》课程的章节 >> {1}'.format(self.course, self.name)
(3)Video 视频
代码如下:
class Video(models.Model): lesson = models.ForeignKey(Lesson, verbose_name="章节",on_delete=models.CASCADE) name = models.CharField("视频名",max_length=100) add_time = models.DateTimeField("添加时间", default=datetime.now) class Meta: verbose_name = "视频" verbose_name_plural = verbose_name
(4)CourseResourse 课程资源
class CourseResource(models.Model): course = models.ForeignKey(Course, verbose_name="课程",on_delete=models.CASCADE) name = models.CharField("名称",max_length=100) download = models.FileField("资源文件",upload_to="course/resource/%Y/%m",max_length=100) add_time = models.DateTimeField("添加时间", default=datetime.now) class Meta: verbose_name = "课程资源" verbose_name_plural = verbose_name
2.3.organization 机构
总共三张表
- CourseOrg 课程机构基本信息
- Teacher 教师基本信息
- CityDict 城市信息
(1)CourseOrg
代码如下:
class CourseOrg(models.Model): name = models.CharField('机构名称',max_length=50) desc = models.TextField('机构描述') click_nums = models.IntegerField('点击数',default=0) fav_nums = models.IntegerField('收藏数',default=0) image = models.ImageField('封面图',upload_to='org/%Y%m',max_length=100) address = models.CharField('机构地址',max_length=150,) city = models.ForeignKey(CityDict,verbose_name='所在城市',on_delete=models.CASCADE) add_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '课程机构' verbose_name_plural = verbose_name
(2)CityDict
代码如下:
class CityDict(models.Model): name = models.CharField('城市',max_length=20) desc = models.CharField('描述',max_length=200) add_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '城市' verbose_name_plural= verbose_name
(3)Teacher
代码如下:
class Teacher(models.Model): org = models.ForeignKey(CourseOrg,verbose_name='所属机构',on_delete=models.CASCADE) name = models.CharField('教师名',max_length=50) work_years = models.IntegerField('工作年限',default=0) work_company = models.CharField('就职公司',max_length=50) work_position = models.CharField('公司职位',max_length=50) points = models.CharField('教学特点',max_length=50) click_nums = models.IntegerField('点击数',default=0) fav_nums = models.IntegerField('收藏数',default=0) add_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '教师' verbose_name_plural = verbose_name def __str__(self): return "[{0}]的教师: {1}".format(self.org, self.name)
2.4.operation
总共五张表
- UseAsk 用户咨询
- UserMessage 用户消息表
- CourseComments 用户评论
- UserCourse 用户学习的课程
- UserFavorite 用户收藏
(1)UserAsk
代码如下:
class UserAsk(models.Model): name = models.CharField('姓名',max_length=20) mobile = models.CharField('手机',max_length=11) course_name = models.CharField('课程名',max_length=50) add_time = models.DateTimeField('添加时间',default=datetime.now) class Meta: verbose_name = '用户咨询' verbose_name_plural = verbose_name def __str__(self): return self.name
(2)UserMessage
user字段,默认0代表消息是发给所有用户,而不是某个单独的用户;可以通过user.id发给特定用户消息
class UserMessage(models.Model): user = models.IntegerField('接受用户',default=0) message = models.CharField('消息内容',max_length=500) has_read = models.BooleanField('是否已读',default=False) add_time = models.DateTimeField('添加时间', default=datetime.now) class Meta: verbose_name = '用户消息' verbose_name_plural = verbose_name
(3)CourseComments
代码如下:
class CourseComments(models.Model): user = models.ForeignKey(UserProfile,verbose_name='用户',on_delete=models.CASCADE) course = models.ForeignKey(Course,verbose_name='课程',on_delete=models.CASCADE) comments = models.CharField('评论',max_length=200) add_time = models.DateTimeField('添加时间', default=datetime.now) class Meta: verbose_name = '课程评论' verbose_name_plural = verbose_name
(4)UserCourse
代码如下:
class UserCourse(models.Model): user = models.ForeignKey(UserProfile,verbose_name='用户',on_delete=models.CASCADE) course = models.ForeignKey(Course,verbose_name='课程',on_delete=models.CASCADE) add_time = models.DateTimeField('添加时间', default=datetime.now) class Meta: verbose_name = '用户课程' verbose_name_plural = verbose_name
(5)UserFavorite
代码如下:
class UserFavorite(models.Model): FAV_TYPE = ( (1,'课程'), (2,'课程机构'), (3,'讲师') ) user = models.ForeignKey(UserProfile,verbose_name='用户',on_delete=models.CASCADE) fav_id = models.IntegerField('数据id',default=0) fav_type = models.IntegerField(verbose_name='收藏类型',choices=FAV_TYPE,default=1) add_time = models.DateTimeField('添加时间', default=datetime.now) class Meta: verbose_name = '用户收藏' verbose_name_plural = verbose_name
上面所有models的完整代码如下:
# users/models.py from datetime import datetime from django.db import models from django.contrib.auth.models import AbstractUser class UserProfile(AbstractUser): gender_choices = ( ('male','男'), ('female','女') ) nick_name = models.CharField('昵称',max_length=50,default='') birthday = models.DateField('生日',null=True,blank=True) gender = models.CharField('性别',max_length=10,choices=gender_choices,default='female') adress = models.CharField('地址',max_length=100,default='') mobile = models.CharField('手机号',max_length=11,null=True,blank=True) image = models.ImageField(upload_to='image/%Y%m',default='image/default.png',max_length=100) class Meta: verbose_name = '用户信息' verbose_name_plural = verbose_name def __str__(self): return self.username class EmailVerifyRecord(models.Model): send_choices = ( ('register','注册'), ('forget','找回密码') ) code = models.CharField('验证码',max_length=20) email = models.EmailField('邮箱',max_length=50) send_type = models.CharField(choices=send_choices,max_length=10) send_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '邮箱验证码' verbose_name_plural = verbose_name class Banner(models.Model): title = models.CharField('标题',max_length=100) image = models.ImageField('轮播图',upload_to='banner/%Y%m',max_length=100) url = models.URLField('访问地址',max_length=200) index = models.IntegerField('顺序',default=100) add_time = models.DateTimeField('添加时间',default=datetime.now) class Meta: verbose_name = '轮播图' verbose_name_plural = verbose_name
# course/models.py from datetime import datetime from django.db import models class Course(models.Model): DEGREE_CHOICES = ( ("cj", "初级"), ("zj", "中级"), ("gj", "高级") ) name = models.CharField("课程名",max_length=50) desc = models.CharField("课程描述",max_length=300) detail = models.TextField("课程详情") degree = models.CharField('难度',choices=DEGREE_CHOICES, max_length=2) learn_times = models.IntegerField("学习时长(分钟数)",default=0) students = models.IntegerField("学习人数",default=0) fav_nums = models.IntegerField("收藏人数",default=0) image = models.ImageField("封面图",upload_to="courses/%Y/%m",max_length=100) click_nums = models.IntegerField("点击数",default=0) add_time = models.DateTimeField("添加时间",default=datetime.now,) class Meta: verbose_name = "课程" verbose_name_plural = verbose_name def __str__(self): return self.name class Lesson(models.Model): course = models.ForeignKey(Course,verbose_name='课程',on_delete=models.CASCADE) name = models.CharField("章节名",max_length=100) add_time = models.DateTimeField("添加时间",default=datetime.now) class Meta: verbose_name = "章节" verbose_name_plural = verbose_name def __str__(self): return '《{0}》课程的章节 >> {1}'.format(self.course, self.name) class Video(models.Model): lesson = models.ForeignKey(Lesson, verbose_name="章节",on_delete=models.CASCADE) name = models.CharField("视频名",max_length=100) add_time = models.DateTimeField("添加时间", default=datetime.now) class Meta: verbose_name = "视频" verbose_name_plural = verbose_name class CourseResource(models.Model): course = models.ForeignKey(Course, verbose_name="课程",on_delete=models.CASCADE) name = models.CharField("名称",max_length=100) download = models.FileField("资源文件",upload_to="course/resource/%Y/%m",max_length=100) add_time = models.DateTimeField("添加时间", default=datetime.now) class Meta: verbose_name = "课程资源" verbose_name_plural = verbose_name
# operation/models.py from datetime import datetime from django.db import models from course.models import Course from users.models import UserProfile class UserAsk(models.Model): name = models.CharField('姓名',max_length=20) mobile = models.CharField('手机',max_length=11) course_name = models.CharField('课程名',max_length=50) add_time = models.DateTimeField('添加时间',default=datetime.now) class Meta: verbose_name = '用户咨询' verbose_name_plural = verbose_name def __str__(self): return self.name class CourseComments(models.Model): user = models.ForeignKey(UserProfile,verbose_name='用户',on_delete=models.CASCADE) course = models.ForeignKey(Course,verbose_name='课程',on_delete=models.CASCADE) comments = models.CharField('评论',max_length=200) add_time = models.DateTimeField('添加时间', default=datetime.now) class Meta: verbose_name = '课程评论' verbose_name_plural = verbose_name class UserFavorite(models.Model): FAV_TYPE = ( (1,'课程'), (2,'课程机构'), (3,'讲师') ) user = models.ForeignKey(UserProfile,verbose_name='用户',on_delete=models.CASCADE) fav_id = models.IntegerField('数据id',default=0) fav_type = models.IntegerField(verbose_name='收藏类型',choices=FAV_TYPE,default=1) add_time = models.DateTimeField('添加时间', default=datetime.now) class Meta: verbose_name = '用户收藏' verbose_name_plural = verbose_name class UserMessage(models.Model): user = models.IntegerField('接受用户',default=0) message = models.CharField('消息内容',max_length=500) has_read = models.BooleanField('是否已读',default=False) add_time = models.DateTimeField('添加时间', default=datetime.now) class Meta: verbose_name = '用户消息' verbose_name_plural = verbose_name class UserCourse(models.Model): user = models.ForeignKey(UserProfile,verbose_name='用户',on_delete=models.CASCADE) course = models.ForeignKey(Course,verbose_name='课程',on_delete=models.CASCADE) add_time = models.DateTimeField('添加时间', default=datetime.now) class Meta: verbose_name = '用户课程' verbose_name_plural = verbose_name
# organization/models.py from datetime import datetime from django.db import models class CityDict(models.Model): name = models.CharField('城市',max_length=20) desc = models.CharField('描述',max_length=200) add_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '城市' verbose_name_plural= verbose_name class CourseOrg(models.Model): name = models.CharField('机构名称',max_length=50) desc = models.TextField('机构描述') click_nums = models.IntegerField('点击数',default=0) fav_nums = models.IntegerField('收藏数',default=0) image = models.ImageField('封面图',upload_to='org/%Y%m',max_length=100) address = models.CharField('机构地址',max_length=150,) city = models.ForeignKey(CityDict,verbose_name='所在城市',on_delete=models.CASCADE) add_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '课程机构' verbose_name_plural = verbose_name class Teacher(models.Model): org = models.ForeignKey(CourseOrg,verbose_name='所属机构',on_delete=models.CASCADE) name = models.CharField('教师名',max_length=50) work_years = models.IntegerField('工作年限',default=0) work_company = models.CharField('就职公司',max_length=50) work_position = models.CharField('公司职位',max_length=50) points = models.CharField('教学特点',max_length=50) click_nums = models.IntegerField('点击数',default=0) fav_nums = models.IntegerField('收藏数',default=0) add_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '教师' verbose_name_plural = verbose_name def __str__(self): return "[{0}]的教师: {1}".format(self.org, self.name)
创建完models后一定要把所有的apps添加到settings的“INSTALLED_APPS”里面
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'users', 'course', 'organization', 'operation', ]
迁移到数据库
python manage.py makemigrations
python manage.py migrate
2.5.把四个app放到一个文件夹
创建package: apps
把之前的四个app全部剪切到apps包里面
不要选“Search for references”
去掉searchfor
的勾选。拖进去之后会报错,说找不到那些import的模块了。
解决方案:右键Mark
为sourceRoot
。根目录下找不到的,会去apps下搜索。
但是这时候cmd下还是会报错。需要在settings设置
插入第0是希望它先搜索我们app下东西:
import os import sys # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0,os.path.join(BASE_DIR,'apps'))
再运行就可以成功启动了
此时的目录