【Django在线教育平台】02.创建该项目用到的数据库模型类

专题:Django2.0.8+xadmin2实现在线学习网站

Django2.0.8+xadmin2实现在线学习网站,课程、讲师、机构、用户收藏功能。GitHub地址:https://github.com/xyliurui/OnlineLearningPlatform ;Django版本:2.0.8

更多内容请点击 我的博客 查看,欢迎来访。

模型设计

  1. users-用户管理
  2. course-课程管理
  3. organization-机构和教师管理
  4. operation-用户操作管理

用户应用users

点击Tools 菜单下 Run manage.py Task

manage.py@DjangoOnlineLearningPlatform > startapp users

用户models

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

  • id: 主键, password 密码, last_login Django自动记录用户最后登录时间,。
  • is_superuser 表明用户是否是超级用户(后台管理会用到)。
  • username 用户名字段不要随便改动, email 邮箱,
  • is_staff 表示是否是员工(后台管理会用到)。
  • is_active 用户是否是激活状态, date_joined 注册时间。

我们需要扩展我们自己的需求字段,例如昵称,生日,性别等。

既要保留原有字段,邮箱添加新的字段,可以使用AbstractUser,点击进去就可以看到User原有的字段

编辑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='', verbose_name='昵称')
    birthday = models.DateField(null=True, blank=True, verbose_name='生日')
    gender = models.CharField(max_length=10, choices=GENDER_CHOICES, default='male', verbose_name='性别')
    address = models.CharField(max_length=100, default='', verbose_name='地址')
    mobile = models.CharField(max_length=11, null=True, blank=True, verbose_name='电话')
    image = models.ImageField(upload_to='image/%Y/%m', default='image/default.png', max_length=100, blank=True, null=True, verbose_name='头像')

    # Meta信息,即后台栏目名
    class Meta:
        verbose_name_plural = verbose_name = '用户信息'

    def __str__(self):
        return self.username

点进AbstractUser可以看到这个models里面就有我们默认表的那些字段。

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

(Venv_learning_platform) D:\Apps\Python>pip install pillow -i https://pypi.douban.com/simple

注意:CharField必须有max_length, Imagefield实际也是charfield所以也要有max_length

注册users应用

修改settings.py文件,添加users应用

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'users',
]

重载AUTH_USER_MODEL

修改settings.py文件,添加以下代码

# 此处重载是为了使我们的UserProfile生效,相当于使用UserProfile替换User表使用
AUTH_USER_MODEL = "users.UserProfile"

同步users数据库

点击Tools 菜单下 Run manage.py Task

manage.py@DjangoOnlineLearningPlatform > makemigrations users
manage.py@DjangoOnlineLearningPlatform > migrate users

循环引用知识

设计app时每个app都有model

BLOG_20190604_133351_48

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

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

循环import会出错。a与b相互调用,造成等待。

解决循环引用: 分层设计

目前已有app:userscoursesorganization

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

BLOG_20190604_133310_77

邮箱验证码和轮播图models

user中还需要添加的(前提是这些功能比较独立):

  • EmailVerifyRecord - 邮箱验证码
  • PageBanner - 轮播图
# 第一块区域import官方包
from datetime import datetime
# 第二块区域import第三方包
from django.db import models
from django.contrib.auth.models import AbstractUser
# 第三块区域import自己定义的


class EmailVerifyRecord(models.Model):
    SEND_CHOICES = (
        ("register", "注册"),
        ("forget", "找回密码")
    )
    code = models.CharField(max_length=20, verbose_name='验证码')
    email = models.EmailField(max_length=50, verbose_name='邮箱')
    send_type = models.CharField(choices=SEND_CHOICES, default='register', max_length=10, verbose_name='发送类型')
    # 这里的now得去掉(), 不去掉会根据编译时间。而不是根据实例化时间
    send_time = models.DateTimeField(default=datetime.now, verbose_name='发送时间')

    class Meta:
        verbose_name_plural = verbose_name = '邮箱验证码'

    def __str__(self):
        return '{}({})'.format(self.code, self.email)


# 1、图片 2. 点击图片地址 3. 轮播图序号(控制前后)
class Banner(models.Model):
    title = models.CharField(max_length=100, verbose_name='标题')
    image = models.ImageField(upload_to='banner/%Y/%m', max_length=100, blank=True, null=True, verbose_name='轮播图')
    url = models.URLField(max_length=200, verbose_name='访问地址')
    # 默认index很大靠后。想要靠前修改index值。
    index = models.IntegerField(default=100, verbose_name='顺序')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

    class Meta:
        verbose_name_plural = verbose_name = '轮播图'

    def __str__(self):
        return self.title

同步users数据库

manage.py@DjangoOnlineLearningPlatform > makemigrations users
manage.py@DjangoOnlineLearningPlatform > migrate users

与用户相关的评论啊,点赞啊。学习的课程啊并没有放进来,因为那些独立性不高。
容易产生循环引用。我们把那些放到operation中。

课程应用courses

点击 Tools 菜单下 Run manage.py Task

manage.py@DjangoOnlineLearningPlatform > startapp courses

course中需要那些表:

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

课程总体结构: 课程本身—(一对多)—>章节—(一对多)—>视频信息

资源下载放在课程里面的。一个课程对应多个资源

共四张表:

  1. 课程本身—(一对多)—>章节----(一对多)---->视频信息
  2. 课程本身—(一对多)—> 资源表
  • Course - 课程基本信息
  • Lesson - 章节信息
  • Video - 视频
  • CourseResource - 课程资源

课程信息models

courses.models.py

from django.db import models
from datetime import datetime


# 课程信息表
class Course(models.Model):
    DEGREE_CHOICES = (
        ("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(max_length=3, choices=DEGREE_CHOICES, 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='course/%Y/%m', max_length=100, blank=True, null=True, 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 = '课程'

    def __str__(self):
        return self.name

课程其他资源models

一对多, 多对一都可以使用django的外键来完成。

# 课程章节
class Lesson(models.Model):
    # 一个课程下有多个章节,需要用到一对多的关系,使用外键完成
    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_plural = verbose_name = '章节'

    def __str__(self):
        return '课程 ' + self.course.name + '的章节:' + self.name


# 课程视频
class Video(models.Model):
    lesson = models.ForeignKey(Lesson, 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_plural = verbose_name = '视频'

    def __str__(self):
        return '章节 ' + self.lesson.name + '的视频:' + self.name


# 课程资源
class CourseResource(models.Model):
    course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name='课程')
    name = models.CharField(max_length=100, verbose_name='名称')
    # 下载的是文件,需要用到文件下载FileField,在后台管理中会自动生成文件上传的按钮
    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_plural = verbose_name = '课程资源'

    def __str__(self):
        return '课程 ' + self.course.name + '的资源:' + self.name

同步courses数据库

settings.py添加courses应用

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'users',
    'courses',
]

执行同步

manage.py@DjangoOnlineLearningPlatform > makemigrations courses
manage.py@DjangoOnlineLearningPlatform > migrate courses

组织机构organization

点击Tools 菜单下 Run manage.py Task

manage.py@DjangoOnlineLearningPlatform > startapp organization

课程是属于机构的, 机构有机构类别,城市等字段。讲师实体。

我要学习的提交表单会与用户关联,存放在机构。

  • CourseOrg - 课程机构基本信息
  • Teacher - 教师基本信息
  • CityDict - 城市信息

课程机构models

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

organization/models.py

from django.db import models
from datetime import datetime


# 城市信息,用户课程机构所在城市选择
class CityDict(models.Model):
    name = models.CharField(max_length=20, verbose_name='城市')
    desc = models.TextField(verbose_name='描述')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

    class Meta:
        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', max_length=100, blank=True, null=True, verbose_name='封面图')
    address = models.CharField(max_length=150, verbose_name='机构地址')
    city = models.ForeignKey(CityDict, on_delete=models.CASCADE, verbose_name='所在城市')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

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

    def __str__(self):
        return self.name


# 机构里的讲师信息
class Teacher(models.Model):
    org = models.ForeignKey(CourseOrg, on_delete=models.CASCADE, related_name='teachers', 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=50, verbose_name='公司职位')
    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_plural = verbose_name = '讲师'

    def __str__(self):
        return self.name

同步organization数据库

settings.py添加organization应用

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'users',
    'courses',
    'organization',
]

同步数据库

manage.py@DjangoOnlineLearningPlatform > makemigrations organization
manage.py@DjangoOnlineLearningPlatform > migrate organization

用户操作operation

分析需要那些表:

  • 用户可以提交我要学习的个人需求。
  • 学员的课程评论信息
  • 收藏:可以收藏公开课, 授课讲师, 授课机构, 用户消息提醒。
  • 个人中心:我的课程说明用户和课程之间的学习关系也需要保存。

模型设计

  • UserAsk - 用户咨询
  • CourseComments - 用户评论
  • UserFavorite - 用户收藏
  • UserMessage - 用户消息
  • UserCourses- 用户学习的课程(用户点击我要学习记录的关联表)

点击Tools 菜单下 Run manage.py Task

manage.py@DjangoOnlineLearningPlatform > startapp operation

用户操作models

from datetime import datetime

from django.db import models

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_plural = verbose_name = '用户咨询'

    def __str__(self):
        return self.name + ' 咨询 ' + self.course_name


# 用户对于课程评论
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=300, verbose_name='评论')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

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

    def __str__(self):
        return self.user.username + ' 评论' + self.course.name


# 用户对于课程,机构,讲师的收藏
class UserFavorite(models.Model):
    # 会涉及四个外键。用户,课程,机构,讲师import
    TYPE_CHOICES = (
        (1, "课程"),
        (2, "课程机构"),
        (3, "讲师")
    )
    user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name='用户')
    # 表明收藏的数据id
    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_plural = verbose_name = '用户收藏'

    def __str__(self):
        return self.user.username + ' 收藏'


# 用户消息
class UserMessage(models.Model):
    # 因为我们的消息有两种:发给全员和发给某一个用户。
    # 所以如果使用外键,每个消息会对应要有用户。很难实现全员消息。
    # 为0发给所有用户,不为0就是发给用户的id
    user = models.IntegerField(default=0, verbose_name="接收用户")
    message = models.CharField(max_length=500, verbose_name="消息内容")
    has_read = models.BooleanField(default=False, verbose_name="是否已读")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

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

    def __str__(self):
        return self.message


# 用户学习课程
class UserCourse(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="用户")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = u"用户课程"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.user.username + ' 学习 ' + self.course.name

同步operation数据库

settings.py添加operation

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'users',
    'courses',
    'organization',
    'operation',
]

执行同步

manage.py@DjangoOnlineLearningPlatform > makemigrations operation
manage.py@DjangoOnlineLearningPlatform > migrate operation

Django2 on_delete配置

TypeError: __init__() missing 1 required positional argument: 'on_delete'

这是因为在2中,外键关系必须指明删除时的操作。

比如:出租车都归属于出租车公司。如果出租车公司倒闭了,那这些汽车该怎么处理。
必须自己指明: 我觉得可以直接进行级联删除。

django提供了:

  • CASCADE
  • PROTECT
  • SET_NULL
  • SET_DEFAULT

等选项。选择了CASCADE删除。

将(dajngo 2)项目中所有的外键修改为如下面代码所示:

也就是添加了on_delete=models.CASCADE使其级联删除。

App集中管理

在项目下新建Python的package: apps

BLOG_20190604_133245_28

把四个app都拖进apps中去。

BLOG_20190604_133240_65

去掉searchfor的勾选。拖进去之后会报错,说找不到那些import的模块了。

BLOG_20190604_133235_32

解决方案:在apps上右键Mark Directory assourceRoot。根目录下找不到的,会去apps下搜索。

但是这时候cmd下运行python manage runserver xxx还是会报错。

将apps添加到python搜索目录下,修改settings.py

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'))  # 添加apps搜索路径

设置静态资源和文件上传路径

设置静态资源路径

settings.py增加

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]
# STATIC_ROOT = os.path.join(BASE_DIR, 'static')

设置文件上传路径

# 设置我们上传文件的路径

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

修改项目中urls.py文件

from django.contrib import admin
from django.urls import path
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

这样,在后台才会正常返回图片或文件的链接。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值