美文网首页
项目介绍和环境配置和数据库表的设计

项目介绍和环境配置和数据库表的设计

作者: 莫辜负自己的一世韶光 | 来源:发表于2018-11-15 15:31 被阅读0次
    • 项目介绍

    • 系统具有完整的用户登录注册功能以及找回密码功能,拥有完整的个人中心

    • 个人中心:修改头像,修改密码,修改邮箱,可以看到我的课程以及我的收藏,可以删除收藏,我的消息

    • 导航栏:公开课,授课老师,授课机构,全局搜索

    • 点击公开课: 课程列表,排序-搜索.热门课程推荐,课程的分页

    • 点击课程: 课程详情页中对课程进行收藏,取消收藏.富文本展示课程内容

    • 点击开始学习: 课程的章节信息,课程的评论信息,课程资源的下载链接

    • 点击授课讲师–>授课讲师列表页,对讲师进行人气排序以及分页,右边有讲师排行榜。

    • 点击讲师的详情页面–> 对讲师进行收藏和分享,以及讲师的全部课程。

    • 导航栏: 授课机构有分页,排序筛选功能。

    • 机构列表页右侧有快速提交我要学习的表单。

    • 点击机构–> 左侧:机构首页,机构课程,机构介绍,机构讲师。

    • 后台管理系统可以切换主题。左侧每一个功能都有列表显示, 增删改查,筛选功能。

    • 课程列表页可以对不同字段进行排序。选择多条记录进行删除操作。

    • 课程列表页:过滤器->选择字段范围等,搜索,导出csv,xml,json。

    • 课程新增页面上传图片,富文本的编辑。时间选择,添加章节,添加课程资源。

    • 日志记录:记录后台人员的操作

    • 前台和后台功能介绍

    • 项目的完整的开发流程

    主要用用到的技术知识点

    • 数据库设计和xadmin搭建后台管理系统任务

    通过业务分析设计django的每个app,设计app下的model。设计外键关系,通过django的migrate设计生成数据表。

    然后将这些model注册到xadmin当中。为每个model配置搜索,过滤字段,以及列表页的显示字段。配置xadmin的主题选择功能。

    • 系统功能模块实现任务

    实现所有后台功能 & 面试中经常被提及的web开发知识。

    几乎所有的django常用模块:

    • settings配置

    • url配置

    • view的书写

    • model设计

    • model和modelform的使用

    • templates模板使用

    • django常用的内置模块

    • web系统知识以及网络安全任务
      防止一些攻击问题

    • sql注入

    • xss攻击

    • crsf攻击
      这些攻击的原理以及防护措施

    xadmin的扩展知识

    掌握更多的定制功能:

    • 权限管理
    • 权限配置
    • 权限,用户,组之间的关系
    • xadmin常用插件
    • 如何自定义xadmin插件
    • xadmin的富文本编辑功能
    • xadmin的excel的导入功能

    还会用到一些开源的django开源库


    • 开发环境的搭建

    1. virtualenv的安装和配置

    virtualenv介绍

    每个应用可能需要各自一套独立的python运行环境.virtualenv就是为了给每个应用创建一套隔离的Python运行环境.

    virtualenv的优点:

    安装virtualenv

    进入cmd
    pip install virtualenv
    virtualenvwrapper安装
    pip install virtualenvwrapper-win
    

    创建虚拟环境

    创建之前,先加一个WORKON_HOME的环境变量


    • 退出激活状态
    deactivate
    
    • 查看有哪些虚拟环境
    workon
    
    • 直接进入虚拟环境
    workon xxx
    
    • 创建虚拟环境
    mkvirtualenv mx_online
    
    • 通过指定的python创建虚拟环境
    mkvirtualenv -p C:\Python36\python.exe mx_online
    

    进入虚拟环境,然后安装相应的必备的依赖包

    进入虚拟环境安装相关的依赖包

    pip install -r C:\Envs\requirements.txt
    

    requirements.txt

    Django==1.11.6
    django-crispy-forms==1.7.2
    django-formtools==2.1
    django-import-export==1.0.1
    django-pure-pagination==0.3.0
    django-ranged-response==0.2.0
    django-simple-captcha==0.5.6
    et-xmlfile==1.0.1
    future==0.16.0
    httplib2==0.9.2
    jdcal==1.4
    odfpy==1.3.6
    openpyxl==2.5.6
    Pillow==5.2.0
    pytz==2018.5
    PyYAML==3.13
    six==1.11.0
    tablib==0.12.1
    unicodecsv==0.14.1
    xlrd==1.1.0
    xlwt==1.3.0
    
    

    安装完毕之后,创建一个Django项目,名字为MxOnline, 环境继承自刚才的虚拟环境

    image.png

    将项目关联到github,创建远程仓库

    2.Django-app 设计

    数据库设计

    根据app设计models

    授课机构提供讲师录制课程,学院完成在线学习.

    • 全局头部: 用户消息&个人中心:没有登录时,就是登录注册
    • 对于公开课,授课老师,授课机构进行搜索
    • 轮播图,课程,机构,页脚
    • 公开课:分页公开课,右边热门推荐
    • 点进课程:课程详情页.详情:后台富文本.右边是课程结构的介绍.收藏或学习
    • 章节信息 & 课程资源下载 & 评论
    • 授课讲师: 授课讲师列表页,讲师排行榜.分页
    • 点进讲师:看到课程
    • 授课机构:类别筛选,机构性质,所在地区 & 排序.用户提交表单,我要学习,机构排名
    • 个人中心:修改密码,修改头像,个人信息,我的课程,我的收藏,我的消息

    app大致分为4个模块

    users - 用户模块
    course - 课程模块
    organization - 机构教师模块
    operation - 用户操作模块

    3.setting.py设置

    • 数据库的配置

    首先确保你的电脑里有mysql应用,然后安装pymysql,分为两个步骤:

    pip install pymysql
    # 然后setting.py中写入以下代码
    
    image.png

    还要在MxOnline/init.py中,声明运用pymysql

    import pymysql
    
    pymysql.install_as_MySQLdb()
    
    

    进行数据库初始化,创建数据库表.注意,之前必须在数据里创建上面设置里面对应的表名mxonline

    点击tools下的Run manage.py Task 或者ctrl + alt + r打开manage.py操作面板

    makemigrations
    migrate
    

    将页面显示的语言设置为中文,并且时间设置为上海时间

    # 语言改为中文
    LANGUAGE_CODE = 'zh-hans'
    
    # 时区改为上海
    TIME_ZONE = 'Asia/Shanghai'
    
    USE_I18N = True
    
    USE_L10N = True
    
    # 数据库存储使用时间,True时间会被存为UTC的时间
    USE_TZ = False
    

    然后运行就可以看到这个界面

    • 3.自定义userprofile

    在manage.py Task下创建app users

    startapp users
    

    编辑我们的model设计user表

    系统自动生成的user表如下:

    个人中心页面:

    可以看到我们还需要:

    • 昵称: nickname
    • 生日:birthday
    • 性别:gender

    User表的自定方法,如果既想保留原有的字段,又想有新字段.
    可以在models.py中创建UserProfile 继承自AbstractUser,然后添加新的属性字段.
    然后在setting.py中重载AUTH_USER_MODEL

    # 此处重载是为了使我们的UserProfile生效
    AUTH_USER_MODEL = "users.UserProfile"
    

    models.py中添加如下代码

    from django.contrib.auth.models import AbstractUser
    from django.db import models
    
    
    class UserProfile(AbstractUser):
        # 自定义的性别选择规则
        GENDER_CHOICES = (
            ('male', '男'),
            ('female', '女')
        )
    
        # 昵称
        nick_name = models.CharField(max_length=50, verbose_name='昵称', default='')
        # 生日可以为空,null=True是针对数据库的,而blank=True是针对表单的.
        # 表示该字段在数据库中可以为空,同时提交表单的时候可以,该字段可以不填.
        birthday = models.DateField(null=True, blank=True, verbose_name='生日')
        # 性别,只能是男或者女.默认是女
        gender = models.CharField(max_length=6, choices=GENDER_CHOICES, default='female', verbose_name='性别')
        # 地址
        address = models.CharField(max_length=100, default='', verbose_name='地址')
        # 电话
        mobile = models.CharField(max_length=11, null=True, blank=True, verbose_name='电话')
    
        # 头像 默认使用default.png
        image = models.ImageField(upload_to='image%Y%m',
                                  default='image/default.png',
                                  max_length=100,
                                  verbose_name='头像')
    
        class Meta:
            verbose_name = '用户信息'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return "<UserProfile: >{}".format(self.username)
    
    

    在setting.py中注册app

    INSTALL_APPS = [
          ...
         'users'
    ]
    

    因为Image字段需要用到pillow所以需要安装该库

    pip install pillow
    

    然后执行

    makemigrations
    migrate
    

    如果出现以下错误

    django.db.migrations.exceptions.InconsistentMigrationHistory: Migration
    admin.0001_initial is applied before its dependency users.0001_initial on
    database 'default'
    

    解决方案:

    删除数据库中 除了auth_user的其他表
    

    删除表的时候,可能会遇到删不掉的情况,就先删除其他的,带有外键关联的表,需要先删除有外键的表

    然后执行命令:

    makemigrations
    migrate
    makemigrations users
    migrate users
    

    共十一张表

    • 4.user models.py的设计

    创建另外三个app,manage.py Task下

    startapp courses
    startapp organization
    startapp operation
    

    循环引用:

    设计app时每个app都有model

    如图:我们在user中定义usercourse记录用户学习的课程.会有两个外键:user和course
    我们就会import Courses.models

    如果用户对课程的评论放到Courses.models当中.评论我们需要保存相应的用户.我们就会import User.models

    两个Models互相引用,就会出现循环导入,a和b相互调用,造成等待.

    解决循环引用: 分层设计

    目前已有app:users courses oranization operation

    另外一个app operation高于这些app的层级.上一层的app可以import下层的app

    user表中还需要添加的(前提是这些功能比较独立,不会和其他的模块产生import,这些顶层的model可以放到user的models.py中)

    • EmailVerifyRecord - 邮箱验证码
    • PageBanner - 轮播图

    users/models.py

    # 邮箱验证码
    class EmailVerifyRecord(models.Model):
        SEND_CHOICES = (
            ('register', '注册'),
            ('forget', '找回密码'),
            ('update_email', '修改邮箱'),
    
        )
        code = models.CharField(max_length=20, verbose_name='验证码')
        email = models.EmailField(max_length=50, verbose_name='邮箱')
        # 验证码的用途,注册和找回密码的时候都可以使用,所以要分类
        send_type = models.CharField(choices=SEND_CHOICES, max_length=20, verbose_name='验证码类型')
        # 这里的now得去掉(),不去掉会根据编译时间。而不是根据实例化时间。
        send_time = models.DateTimeField(default=datetime.now, verbose_name='发送时间')
    
        class Meta:
            verbose_name = '邮箱验证码'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return "<EmailVerifyRecord: >{}".format(self.code)
    
    
    class Banner(models.Model):
        title = models.CharField(max_length=100, verbose_name='标题')
        # 保存到数据库的时候存储的是url地址
        image = models.ImageField(max_length=100, upload_to='banner/%Y/%m', verbose_name='轮播图')
        url = models.URLField(max_length=200, verbose_name='访问地址')
        # 控制轮播图的顺序
        index = models.IntegerField(default=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.title, self.index)
    

    Courses/models.py的编写

    课程本身需要一张表

    点进去之后

    • 点进去之后开始学习
    • 课程基本信息需要一张表,章节表与课程表存在多对一的关系(一个课程对应多个章节)
    • 章节表中:章节的名称,章节与食品(一个章节对应多个视频)

    结构: 课程本身 -- (一对多) > 章节 (一对多) -> 视频信息
    资源下载放在课程里面的,一个课程对应多个资源.

    共四张表:
    课程本身(一对多)章节 -> (一对多) -> 视频信息 & 资源表


    课程表的编写,注意他们之间的表的对应关系

    from datetime import datetime
    
    from django.db import models
    
    
    # 课程信息表
    class Course(models.Model):
        DegreeChoices = (
            ('cj', '初级'),
            ('zj', '中级'),
            ('gj', '高级')
        )
        name = models.CharField(max_length=50, verbose_name='课程名称')
        desc = models.CharField(max_length=300, verbose_name='课程描述')
        # 后期会替换为富文本的模式
        detail = models.TextField(verbose_name='课程详情')
        degree = models.CharField(choices=DegreeChoices, max_length=2)
        learn_time = 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='点击数')
        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 = models.ForeignKey(Course, 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)
    
    
    # 视频表
    class Video(models.Model):
        lesson = models.ForeignKey(Lesson, 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.lesson, self.name)
    
    
    # 课程资源表
    class ResourceCourse(models.Model):
        # course相关
        course = models.ForeignKey(Course, verbose_name='课程')
        name = models.CharField(max_length=100, verbose_name='名称')
        download = models.FileField(upload_to='course/resource/%Y/%m', 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)
    
    

    通过Structure可以看到我们刚才设计了四张表

    organization(课程机构表)的编写 organization/models.py

    课程是属于机构,机构有机构类别,城市等字段.讲师实体.
    我要学习的提交表单会与用户关联,存放在机构.


    点击具体的课程:


    其中课程数,学习人数可以动态统计.机构地址,机构经典课程.

    机构讲师,机构课程可以通过外键获取到,不保存到机构中


    对应的models.py如下

    from datetime import datetime
    
    from django.db import models
    
    
    class CityDict(models.Model):
        name = models.CharField(max_length=20, verbose_name='城市')
        desc = models.CharField(max_length=200, verbose_name='描述')
        add_time = models.DateTimeField(default=datetime.now)
    
        class Meta:
            verbose_name = '城市'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class CourseOrg(models.Model):
        name = models.CharField(max_length=50, verbose_name='机构名称')
        desc = models.TextField(verbose_name='机构描述')
        click_nums = models.IntegerField(default=0, verbose_name='点击数')
        fav_nums = models.IntegerField(default=0, verbose_name='收藏')
        image = models.ImageField(upload_to='org/%Y/%m', verbose_name='封面图')
        address = models.CharField(max_length=150, verbose_name='机构地址')
    
        # 城市外键
        city = models.ForeignKey(CityDict, verbose_name='所在城市')
        add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')
    
        class Meta:
            verbose_name = '课程机构'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return '课程机构: {}'.format(self.name)
    
    
    # 教师信息表
    class Teacher(models.Model):
        # 外键,一个机构可以对应多个老师
        org = models.ForeignKey(CourseOrg, verbose_name='所属机构')
        name = models.CharField(max_length=50, verbose_name='教师名')
        work_years = models.IntegerField(default=0, verbose_name='工作年限')
        work_company = models.CharField(max_length=50, verbose_name='就职公司')
        work_position = models.CharField(max_length=100, 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='收藏数')
        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.org, self.name)
    
    

    我们可以看到,organization/models.py中一共具有三张表


    operation/models.py设计

    分析需要哪些表:

    • 用户可以提交我要学习的个人需求
    • 学员的课程评论信息
    • 收藏:可以收藏公开课,授课讲师,授课机构,用户消息提醒.
    • 个人中心:我的课程, 说明用户和课程之间的学习关系也需要保存.
    from datetime import datetime
    
    from django.db import models
    
    # 用户我要学习表单,用户咨询
    from courses.models import Course
    from users.models import UserProfile
    
    
    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 '用户: {0} 手机号: {1}'.format(self.name, self.mobile)
    
    
    # 用户对于课程的评论
    class CourseComments(models.Model):
        # 会涉及到两个外键,1.用户 2.课程 import进来
        course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name='课程')
        user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name='用户')
        comments = models.CharField(max_length=250, 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.user, self.course)
    
    
    # 用户对于课程,机构,讲师的收藏
    class UserFavorite(models.Model):
        # 选择收藏的类别
        TYPE_CHOICES = (
            (1, '课程'),
            (2, '课程机构'),
            (3, '讲师')
        )
        user = models.ForeignKey(UserProfile, verbose_name='用户')
        fav_id = models.IntegerField(default=0, verbose_name='数据id')
        fav_type = models.IntegerField(choices=TYPE_CHOICES, default=1, 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.user, self.fav_type)
    
    
    # 用户消息表
    class UserMessage(models.Model):
        # user为0的时候,发送给所有.
        user = models.IntegerField(default=0, verbose_name='接收用户')
        message = models.CharField(max_length=500, verbose_name='消息内容')
        has_read = models.BooleanField(default=False)
        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.user, self.message)
    
    # 用户课程表
    class UserCourse(models.Model):
        # 会涉及两个外键: 1.用户  2.课程
        course = models.ForeignKey(Course,on_delete=models.CASCADE,verbose_name='课程')
        user = models.ForeignKey(UserProfile,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 '用户({0})学习了{1} '.format(self.user, self.course)
    
    

    到这里我们所有的models都设计完毕.operation/models.py


    settings.py中添加配置app

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        # 注册app
        'users',
        'organization',
        'courses',
        'operation',
    ]
    

    数据表的生成以及apps目录的建立

    打开manage.py 的Task

    makemigrations
    migrate
    

    生成如下的表:


    把我们的四个app放到一个文件夹下.

    新建Python的package:apps
    然后将四个app拖进去,注意不要选择下面的选项

    然后将apps包右键mark为sourceRoot.根目录下找不到,会去apps目录下搜索.

    但是这时候cmd下还是会报错

    解决方法:

    将apps设置到我们的系统搜索目录之下

    相关文章

      网友评论

          本文标题:项目介绍和环境配置和数据库表的设计

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