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

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

作者: 啃饼小白 | 来源:发表于2018-07-27 07:21 被阅读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

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/dubymftx.html