零基础使用Django2.0.1打造在线教育网站

零基础使用Django2.0.1打造在线教育网站(八):数据库字

2018-07-27  本文已影响35人  啃饼小白

写在前面

本篇笔记主要完善其余3个apps应用的数据库字段的定义,在此之前希望小伙伴们好好回忆之前关于users应用的数据库字段定义的方法,这对接下来的其余apps应用的创建有很大帮助(可以照葫芦画瓢)。

本篇笔记对应于第八篇代码,对应于github的位置是https://github.com/licheetools/eduline

3个apps应用的创建

1、课程版块(course)

a、创建courses应用

先点击菜单下的Tools按钮 ,然后点击下拉的 Run manage.py Task按钮,在命令行中输入:

startapp courses

b、确定数据库中的数据表数量

首先,课程本身需要一张表用于保存自身信息:

随意点开一门课程,你会发现以下内容:



点击右侧的开始学习,你会进入章节信息详情:

每个课程包含多个章节,每个章节下面又包含多个视频和右侧的课程资料。其中:

课程和章节是一对多的映射关系;章节和视频也是一对多的映射关系;课程和资料也是一对多的映射关系。所以通过分析,我们需要新建4个表,用于信息的存取:

c、开始数据库字段的定义

打开我们的courses/models.py文件,添加并修改如下代码:

from django.db import models
from datetime import datetime
# Create your models here.

# 课程信息
class Course(models.Model):
    name = models.CharField(max_length=50, verbose_name="课程名")
    # 描述这一块,我们先用TextField,因为它允许我们不输入长度,而且可以输入值无范围,之后再更新为富文本形式
    desc = models.CharField(max_length=300, verbose_name="课程描述")
    detail = models.TextField(max_length=500, verbose_name="课程详情")
    is_banner = models.BooleanField(default=False, verbose_name="是否轮播")
    degree = models.CharField(max_length=2, 
choices=(('cj', '初级'), ('zj', '中级'), ('gj', '高级')), verbose_name="难度等级")
    # 学习数这里使用分钟数作计量单位,便于后台记录(存储最小单位)和前台转换
    learn_times = models.IntegerField(default=0, verbose_name="学习时长(分钟数)")
    # 学习人数从点击开始学习算起
    students = models.IntegerField(default=0, verbose_name="学习人数")
    # 收藏人数从点击收藏按钮算起
    fav_nums = models.IntegerField(default=0, verbose_name="收藏人数")
    image = models.ImageField(upload_to='courses/%Y/%m', max_length=100, verbose_name="封面图片")
    # 点击数从点击页面算起
    click_nums = models.IntegerField(default=0, verbose_name="点击数")
    category = models.CharField(default="后端开发", max_length=20, verbose_name="课程类别")
    tag = models.CharField(default='', max_length=10, verbose_name="课程标签")
    youneeded_know = models.CharField(default='', max_length=300, verbose_name="课程须知")
    teacher_tell = models.CharField(default='', max_length=300, verbose_name="老师告诉你")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "课程"
        verbose_name_plural = verbose_name
        
    def __str__(self):
        return self.name
    

接着刚才的代码,我们在下面添加如下内容:

# 章节信息
class Lesson(models.Model):
    # 前面知道一个课程对应多个章节,所以在章节表中将课程设置为外键。
    # 此处的course其实就是一个用来告诉我们这个章节属于哪个课程的字段
    course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name="课程")
    name = models.CharField(max_length=100, verbose_name="章节名")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "章节"
        verbose_name_plural = verbose_name

    def __str__(self):
        # 采用了字符串的格式化方式来同时引用多个数据
        return '<<{0}>>课程的章节》{1}'.format(self.course, self.name)  
        # return self.name也是可以

在上面的外键字course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name="课程"),这其实就是一个用于告知信息的字段,包含3个参数:Course是指你与哪个对象存在外键关系(记住是表的名称,不是字段的名称);on_delete=models.CASCADE是指主外关系键中,级联删除,也就是当删除主表的数据时候从表中的数据也随着一起删除;verbose_name就是你定义字段的别称(后台管理中显示)

我们继续接着刚才的代码,我们在下面添加如下内容:

# 视频信息
class Video(models.Model):
    # 前面知道一个章节对应多个视频,所以在视频表中将章节设置为外键。
    # 此处的lesson其实就是一个用来告诉我们这个视频属于哪个章节的字段
    lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE, verbose_name="章节")
    name = models.CharField(max_length=100, verbose_name="视频名称")
    url = models.URLField(max_length=200, default='', verbose_name="访问地址")
    learn_times = models.IntegerField(default=0, verbose_name="学习时长(分钟数)")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "视频"
        verbose_name_plural = verbose_name

    def __str__(self):
        return '<<{0}>>章节的视频》{1}'.format(self.lesson, self.name)   # return self.name也是可以

# 课程资料信息
class CourseResource(models.Model):
    # 前面知道一个课程对应多个课程资料,所以在课程资料表中将课程设置为外键。
    # 此处的course其实就是一个用来告诉我们这个课程资料属于哪个课程的字段
    course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name="课程")
    name = models.CharField(max_length=100, verbose_name="名称")
    download = models.FileField(max_length=100, upload_to='course/resource/%Y/%m', 
verbose_name="资源文件")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
    
    class Meta:
        verbose_name = "课程资源"
        verbose_name_plural = verbose_name
        
    def __str__(self):
        return '<<{0}>>课程的课程资料》{1}'.format(self.course, self.name)   # return self.name也行
点击左侧的structure,我们可以看到如下的4个函数(数据表):

至此,我们course应用的数据库字段的定义到此告一段落,不过以后可能会有新的字段加入,所以我们就先不进行数据库生成和迁移操作。

2、授课教师与授课机构板块(organization)

a、创建organization应用

先点击菜单下的Tools按钮 ,然后点击下拉的 Run manage.py Task按钮,在命令行中输入:

startapp organization

b、确定数据库中的数据表数量

顾名思义授课教师与授课机构板块,里面肯定有授课教师和授课机构这2个表吧。然后我们来观察一下页面:

看到没有,里面有一个用于筛选的城市列表,所以这个内容我们也是要单独放在一张表里面的。

也就是说,我们需要新建3张表:

其中,课程是属于课程机构的, 课程机构又有机构类别,城市,授课讲师等字段。


上面则是教师信息表应当具有的一些字段。

c、开始数据库字段的定义

打开我们的organization/models.py文件,添加并修改如下代码:

from django.db import models
from datetime import datetime
# Create your models here.


# 城市信息
class CityDict(models.Model):
    name = models.CharField(max_length=20, verbose_name="城市")
    # 描述这一块,我们先用TextField,因为它允许我们不输入长度,而且可以输入值无范围,之后再更新为富文本形式
    desc = models.CharField(max_length=200, verbose_name="描述")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "城市"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name   # 这里很重要,否则在后台就显示不出Meta信息


# 课程机构
class CourseOrg(models.Model):
    name = models.CharField(max_length=50, verbose_name="机构名称")
    desc = models.TextField(verbose_name="机构描述")
    tag = models.CharField(max_length=10, default="全国知名", verbose_name="机构标签")
    category = models.CharField(max_length=20, default='pxjg', 
choices=(('pxjg', '培训机构'), ('gr', '个人'), ('gx', '高校')), verbose_name="机构类别")
    click_nums = models.IntegerField(default=0, verbose_name='点击数')
    fav_nums = models.IntegerField(default=0, verbose_name='收藏数')
    image = models.ImageField(max_length=50, upload_to="org/%Y/%m", verbose_name="logo")
    address = models.CharField(max_length=150, verbose_name="机构地址")
    # 前面知道一个城市对应多个课程机构,所以在课程机构表中将城市设置为外键。
    # 此处的city其实就是一个用来告诉我们这个课程机构属于哪个城市的字段
    city = models.ForeignKey(CityDict, on_delete=models.CASCADE, verbose_name="所在城市说明")
    students = models.IntegerField(default=0, verbose_name="学习人数")
    course_nums = models.IntegerField(default=0, verbose_name="课程数")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "课程机构"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name   # 这里很重要,否则在后台就显示不出Meta信息


# 教师信息
class Teacher(models.Model):
    # 前面知道一个课程机构对应多个教师,所以在教师信息表中将授课机构设置为外键。
    # 此处的org其实就是一个用来告诉我们这个教师属于哪个课程机构的字段
    org = models.ForeignKey(CourseOrg, on_delete=models.CASCADE, verbose_name="所属教师")
    name = models.CharField(max_length=50, verbose_name="教师名")
    work_years = models.IntegerField(default=0, verbose_name="工作年限")
    work_position = models.CharField(max_length=50, verbose_name="公司职位")
    work_company = models.CharField(max_length=50, verbose_name="就职公司")
    points = models.CharField(max_length=50, verbose_name="教学特点")
    click_nums = models.IntegerField(default=0, verbose_name="点击数")
    fav_nums = models.IntegerField(default=0, verbose_name='收藏数')
    age = models.IntegerField(default=18, verbose_name='年龄')
    image = models.ImageField(default='', upload_to='teacher/%Y/%m', 
verbose_name='头像', max_length=100)
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "教师"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name   # 这里很重要,否则在后台就显示不出Meta信息

点击左侧的structure,我们可以看到如下的3个函数(数据表):

3、用户操作板块(operation)

a、创建operation应用

先点击菜单下的Tools按钮 ,然后点击下拉的 Run manage.py Task按钮,在命令行中输入:

startapp operation

b、确定数据库中的数据表数量

这个app应用主要用于用户操作信息的记录,主要包括:

1、用户提交我要学习的个人需求记录;
2、用户的课程评论信息记录;
3、用户用于收藏公开课, 授课讲师, 授课机构以及用户消息提醒的记录;
4、用户个人中心里面我的课程说明,用户和课程之间的学习信息记录;
5、用户咨询消息的记录等。

如下图所示:

c、开始数据库字段的定义

打开我们的operation/models.py文件,添加并修改如下代码:

from django.db import models
from datetime import datetime
# Create your models here.

from users.models import UserProfile
from courses.models import Course


# 用户我要学习信息
class UserAsk(models.Model):
    name = models.CharField(max_length=20, verbose_name="姓名")
    mobile = models.CharField(max_length=11, verbose_name="手机")
    course_name = models.CharField(max_length=50, verbose_name="课程名")
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

    class Meta:
        verbose_name = "用户咨询"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name    # 这里很重要,否则在后台就显示不出Meta信息


# 课程评论
class CourseComments(models.Model):
    # 前面知道一个用户发表多个课程评论,所以在课程评论表中将用户设置为外键。
    # 此处的user其实就是一个用来告诉我们这个课程评论属于哪个用户的字段
    user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name="用户名")
    # 前面知道一门课程具有多个课程评论,所以在课程评论表中将课程设置为外键。
    # 此处的course其实就是一个用来告诉我们这个课程评论属于哪个课程的字段
    course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name="课程")
    comment = models.CharField(max_length=200, verbose_name="评论")
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

    class Meta:
        verbose_name = '课程评论'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.comment   # 这里很重要,否则在后台就显示不出Meta信息


# 用户收藏信息
class UserFavorite(models.Model):
    # 前面知道一个用户可以收藏多个内容,所以在用户收藏表中将用户设置为外键。
    # 此处的user其实就是一个用来告诉我们这个用户收藏属于哪个用户的字段
    user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name="用户名")
    fav_id = models.IntegerField(default=0, verbose_name='数据Id')
    fav_type = models.CharField(choices=(('1', '课程'), ('2', '课程机构'), ('3', '讲师')), default=1, 
verbose_name='收藏类型',max_length=2)
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

    class Meta:
        verbose_name = "用户收藏"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.user   # 这里很重要,否则在后台就显示不出Meta信息


# 用户消息信息
class UserMessage(models.Model):
    # 我们的消息有两种:一种是发给全员,另一种则是发给特定某一个用户。
    # 所以如果使用外键,那么每个消息就要对应一个用户,比较难以实现全员消息的通知。
    # 因此我们设置用户id,如果为0就发给所有用户,不为0就是发给特定Id的用户。
    user = models.IntegerField(default=0, verbose_name="接收用户")
    message = models.CharField(max_length=500, verbose_name='消息内容')
    # 设置消息是否已读,采用布尔类型 BooleanField: False表示未读,True表示已读。
    has_read = models.BooleanField(default=False, verbose_name='是否已读')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

    class Meta:
        verbose_name = '用户消息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.message  # 这里很重要,否则在后台就显示不出Meta信息


# 用户课程信息
class UserCourse(models.Model):
    # 前面知道一个用户可以学习多门课程,所以在用户课程表中将用户设置为外键。
    # 此处的user其实就是一个用来告诉我们这个课程属于哪个用户的字段
    user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name='用户名')
    # 前面知道一门课程可以有多个课程的信息,所以在用户课程表中将课程设置为外键。
    # 此处的course其实就是一个用来告诉我们这个课程信息属于哪门课程的字段
    course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name='课程')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='学习时间')

    class Meta:
        verbose_name = '用户课程'
        verbose_name_plural = verbose_name

        def __str__(self):
            return self.user  # 这里很重要,否则在后台就显示不出Meta信息

点击左侧的structure,我们可以看到如下的5个函数(数据表):

至此,我们所有apps都已经创建完成,它们所包含的数据库字段的定义也都完成。

注册我们的4个apps

打开eduline/settings.py文件,找到第33行代码,在其中加入以下代码:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users',
    'courses',
    'organization',
    'operation',
]
如图所示:

数据库生成和迁移操作

先点击菜单下的Tools按钮 ,然后点击下拉的 Run manage.py Task按钮,在命令行中输入:

makemirgration
migrate

上面是对所有apps都进行数据库生成和迁移操作,如果你想对某个app操作,你可以使用下面的命令:

makemirgration appname
migrate appname


上图分别为makemirgrations和migrate过程中输出的信息。下图是由于我们做的改动导致文件的变动记录:
courses/migrations/0001_initial.py:这个文件是我们migrations时生成的新initial文件,这是很重要的变动文件,不能随意删除。

打开Navicat,查看数据表

我们看到许多自定义的表都已经有了,而且命名规则都是 app名称 + 我们的类名转变为小写

现在我们打开django_migrations表去查看一下我们的migration记录:

0001_inital是初始文件,其他的表明该应用已经在运行了。

新建管理文件夹

现在你看我们的目录树结构已经变成了这样:

所有的应用apps都是直接裸露在树干上,如果有10个,甚至更多100个呢?这样的管理方式就显得很混乱,业务逻辑分离不够明显。这时,我们可以新建一个文件夹,专门用于apps的管理。

新建一个Python package,名字叫apps,把我们之前的4个apps都拖进去:
不要勾选search for references,直接点击确定即可。


现在就变成了这个结构,是不是好看多了:
不过上面那种操作会出问题,系提示找不到那些import的模块:
还得我们前面在回顾Django基础知识的时候,也出现过类似的情况,忘了的话可以查看这篇笔记:零基础使用Django2.0.1打造在线教育网站(三):Django基础知识回顾

这里我们就直接设置文件查找路径了。
打开eduline/settings.py文件,找到里面的第16行代码,我们加入以下内容:

import os, 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'))

在上面,os是用于输入输出的库,前面输出的是当前的项目主目录,后面输出的则是apps这个目录,我们这里采用os.path.join()函数,将项目的绝对路径与apps进行拼接,返回一个新的地址,插入第0是希望它首先在apps下面搜索我们的内容。

测试运行一下项目

先点击菜单下的Tools按钮 ,然后点击下拉的 Run manage.py Task按钮,在命令行中输入:runserver再回车:


在浏览器地址栏中输入http://127.0.0.1:8000/或者http://127.0.0.1,出现:
恭喜你,我们的Django网页已经跑起来了。

至此,我们关于在线教育网站项目的app应用的创建和数据库字段的定义就到此结束了,感谢你的赏阅!

下一篇笔记,我们就开始进行后台的管理和配置了!

本篇笔记对应于第八篇代码,对应于github的位置是https://github.com/licheetools/eduline

上一篇下一篇

猜你喜欢

热点阅读