4-5 user modesl.py设计

循环引用:

设计app时每个app都有model

 
mark

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

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

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

解决循环引用: 分层设计

目前已有app:users courses organization

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

 
mark

上节中: 自定义userprofile 覆盖默认user

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

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

观察轮播图:

  1. 图片 2. 点击图片地址 3. 轮播图序号(控制前后)
 
mark

users/models.py中添加代码:

from datetime import datetime

# 邮箱验证码model

class EmailVerifyRecord(models.Model):
SEND_CHOICES = (
("register", u"注册"),
("forget", u"找回密码")
)
code = models.CharField(max_length=20, verbose_name=u"验证码")
# 未设置null = true blank = true 默认不可为空
email = models.EmailField(max_length=50, verbose_name=u"邮箱")
send_type = models.CharField(choices=SEND_CHOICES, max_length=10)
# 这里的now得去掉(),不去掉会根据编译时间。而不是根据实例化时间。
send_time = models.DateTimeField(default=datetime.now) class Meta:
verbose_name = "邮箱验证码"
verbose_name_plural = verbose_name # 轮播图model class Banner(models.Model):
title = models.CharField(max_length=100, verbose_name=u"标题")
image = models.ImageField(
upload_to="banner/%Y/%m",
verbose_name=u"轮播图",
max_length=100)
url = models.URLField(max_length=200, verbose_name=u"访问地址")
# 默认index很大靠后。想要靠前修改index值。
index = models.IntegerField(default=100, verbose_name=u"顺序")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"轮播图"
verbose_name_plural = verbose_name

从上往下: 第一块区域import官方包,第二块import第三方。(PEP8)

 
mark

如下图: 我们一共创建了三个数据表: Structure可以查看到

 
mark

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

本小节完成,对应commit:

Usermodel添加邮箱验证码,首页轮播图。对应4-5

4-6 course models.py编写

点击 Tools 菜单下 Run manage.py Task

startapp courses

course中需要那些表:

  • 课程本身需要一张表
 
mark
 
mark
  • 点进去之后点击开始学习。

  • 课程基本信息需要一张表, 章节表与课程表存在(一个课程对应多个章节)

  • 章节表中:章节的名称。 章节与视频(一个章节对应多个视频)

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

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

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

 
mark

courses/models.py:

from datetime import datetime

# 课程信息表
class Course(models.Model):
DEGREE_CHOICES = (
("cj", u"初级"),
("zj", u"中级"),
("gj", u"高级")
)
name = models.CharField(max_length=50, verbose_name=u"课程名")
desc = models.CharField(max_length=300, verbose_name=u"课程描述")
# TextField允许我们不输入长度。可以输入到无限大。暂时定义为TextFiled,之后更新为富文本
detail = models.TextField(verbose_name=u"课程详情")
degree = models.CharField(choices=DEGREE_CHOICES, max_length=2)
# 使用分钟做后台记录(存储最小单位)前台转换
learn_times = models.IntegerField(default=0, verbose_name=u"学习时长(分钟数)")
# 保存学习人数:点击开始学习才算
students = models.IntegerField(default=0, verbose_name=u"学习人数")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏人数")
image = models.ImageField(
upload_to="courses/%Y/%m",
verbose_name=u"封面图",
max_length=100)
# 保存点击量,点进页面就算
click_nums = models.IntegerField(default=0, verbose_name=u"点击数")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"课程"
verbose_name_plural = verbose_name

下面来编写章节 & 视频 & 课程资源:courses/models.py

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

# 章节
class Lesson(models.Model):
# 因为一个课程对应很多章节。所以在章节表中将课程设置为外键。
# 作为一个字段来让我们可以知道这个章节对应那个课程
course = models.ForeignKey(Course, verbose_name=u"课程")
name = models.CharField(max_length=100, verbose_name=u"章节名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"章节"
verbose_name_plural = verbose_name # 每章视频
class Video(models.Model):
# 因为一个章节对应很多视频。所以在视频表中将章节设置为外键。
# 作为一个字段来存储让我们可以知道这个视频对应哪个章节.
lesson = models.ForeignKey(Lesson, verbose_name=u"章节")
name = models.CharField(max_length=100, verbose_name=u"视频名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"视频"
verbose_name_plural = verbose_name # 课程资源
class CourseResource(models.Model):
# 因为一个课程对应很多资源。所以在课程资源表中将课程设置为外键。
# 作为一个字段来让我们可以知道这个资源对应那个课程
course = models.ForeignKey(Course, verbose_name=u"课程")
name = models.CharField(max_length=100, verbose_name=u"名称")
# 这里定义成文件类型的field,后台管理系统中会直接有上传的按钮。
# FileField也是一个字符串类型,要指定最大长度。
download = models.FileField(
upload_to="course/resource/%Y/%m",
verbose_name=u"资源文件",
max_length=100)
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"课程资源"
verbose_name_plural = verbose_name

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

 
mark

本小节完毕, 对应commit:

设计完成课程app中四张数据表: 课程,章节,视频,资源。对应4-6

4-7 organization modesl.py设计

新建课程机构app:

点击Tools 菜单下 Run manage.py Task

startapp organization

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

 
mark
 
mark

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

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

 
mark

讲师大概所需要的字段如图所示。

organization/models.py 代码如下:

# encoding : utf-8
from datetime import datetime from django.db import models # Create your models here. # 城市字典
class CityDict(models.Model):
name = models.CharField(max_length=20, verbose_name=u"城市")
# 城市描述:备用不一定展示出来
desc = models.CharField(max_length=200, verbose_name=u"描述")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"城市"
verbose_name_plural = verbose_name # 课程机构
class CourseOrg(models.Model):
name = models.CharField(max_length=50, verbose_name=u"机构名称")
# 机构描述,后面会替换为富文本展示
desc = models.TextField(verbose_name=u"机构描述")
click_nums = models.IntegerField(default=0, verbose_name=u"点击数")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏数")
image = models.ImageField(
upload_to="org/%Y/%m",
verbose_name=u"封面图",
max_length=100)
address = models.CharField(max_length=150, verbose_name=u"机构地址")
# 一个城市可以有很多课程机构,通过将city设置外键,变成课程机构的一个字段
# 可以让我们通过机构找到城市
city = models.ForeignKey(CityDict, verbose_name=u"所在城市")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"课程机构"
verbose_name_plural = verbose_name # 讲师
class Teacher(models.Model):
# 一个机构会有很多老师,所以我们在讲师表添加外键并把课程机构名称保存下来
# 可以使我们通过讲师找到对应的机构
org = models.ForeignKey(CourseOrg, verbose_name=u"所属机构")
name = models.CharField(max_length=50, verbose_name=u"教师名称")
work_years = models.IntegerField(default=0, verbose_name=u"工作年限")
work_company = models.CharField(max_length=50, verbose_name=u"就职公司")
work_position = models.CharField(max_length=50, verbose_name=u"公司职位")
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 = u"教师"
verbose_name_plural = verbose_name
 
mark

可以看到我们一共创建了三张表:分别是城市,课程机构,讲师。

本小节对应commit:

课程机构app:城市,机构,讲师表书写完毕。对应4-7

4-8 operation models.py设计

分析需要那些表:

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

新建操作app:

点击Tools 菜单下 Run manage.py Task

startapp operation

operation/models.py添加代码:

# encoding: utf-8
from datetime import datetime # 引入我们CourseComments所需要的外键models
from users.models import UserProfile
from courses.models import Course # 用户我要学习表单
class UserAsk(models.Model):
name = models.CharField(max_length=20, verbose_name=u"姓名")
mobile = models.CharField(max_length=11, verbose_name=u"手机")
course_name = models.CharField(max_length=50, verbose_name=u"课程名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"用户咨询"
verbose_name_plural = verbose_name # 用户对于课程评论
class CourseComments(models.Model): # 会涉及两个外键: 1. 用户, 2. 课程。import进来
course = models.ForeignKey(Course, verbose_name=u"课程")
user = models.ForeignKey(UserProfile, verbose_name=u"用户")
comments = models.CharField(max_length=250, verbose_name=u"评论")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"评论时间") class Meta:
verbose_name = u"课程评论"
verbose_name_plural = verbose_name # 用户对于课程,机构,讲师的收藏
class UserFavorite(models.Model):
# 会涉及四个外键。用户,课程,机构,讲师import
TYPE_CHOICES = (
(1, u"课程"),
(2, u"课程机构"),
(3, u"讲师")
) user = models.ForeignKey(UserProfile, verbose_name=u"用户")
# course = models.ForeignKey(Course, verbose_name=u"课程")
# teacher = models.ForeignKey()
# org = models.ForeignKey()
# fav_type = # 机智版
# 直接保存用户的id.
fav_id = models.IntegerField(default=0)
# 表明收藏的是哪种类型。
fav_type = models.IntegerField(
choices=TYPE_CHOICES,
default=1,
verbose_name=u"收藏类型")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"评论时间") class Meta:
verbose_name = u"用户收藏"
verbose_name_plural = verbose_name # 用户消息表
class UserMessage(models.Model):
# 因为我们的消息有两种:发给全员和发给某一个用户。
# 所以如果使用外键,每个消息会对应要有用户。很难实现全员消息。 # 机智版 为0发给所有用户,不为0就是发给用户的id
user = models.IntegerField(default=0, verbose_name=u"接收用户")
message = models.CharField(max_length=500, verbose_name=u"消息内容") # 是否已读: 布尔类型 BooleanField False未读,True表示已读
has_read = models.BooleanField(default=False, verbose_name=u"是否已读")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"用户消息"
verbose_name_plural = verbose_name # 用户课程表
class UserCourse(models.Model):
# 会涉及两个外键: 1. 用户, 2. 课程。import进来
course = models.ForeignKey(Course, verbose_name=u"课程")
user = models.ForeignKey(UserProfile, verbose_name=u"用户")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"用户课程"
verbose_name_plural = verbose_name

至此:我们的五张operation下的数据表models设计完成

 
mark

setting中配置添加app

 
mark

本小节对应commit:

operation下的models设计,用户: 课程&消息&收藏&评论&我要学习.并在setting中进行了注册。对应4-8

4-9 数据表生成以及apps目录建立

学习如何通过刚才设计的models生成数据库对应的表

点击Tools 菜单下 Run manage.py Task:

Python2与Python3不同:

Python2下可能会报一些noASCII错误:

只需要在对应你写了中文的第一行加上:

# encoding: utf-8

Python3(django2.0.1)会报错:

org = models.ForeignKey(CourseOrg, verbose_name=u"所属机构")
TypeError: __init__() missing 1 required positional argument: 'on_delete'

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

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

django提供了:

  • CASCADE
  • PROTECT
  • SET_NULL
  • SET_DEFAULT

等选项。我选择了CASCADE删除。

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

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

org = models.ForeignKey(CourseOrg, on_delete=models.CASCADE, verbose_name=u"所属机构")

makemirgration & migrate生成表

makemirgration
migrate
 
mark

上图为makemirgration过程中输出的信息。可以看到我们做出的改动

 
mark

此时我们查看app目录中migrations文件夹可以看到产生的新文件。

operation/migrations/0001_initial.py:

可以看到里面也是Python的语法。他会帮我们生成数据表。
以后每次migrations时都会生成新的initial文件。这是很重要的变动文件,不能随意删除。

打开Navicat可以看到django的数据库中有它默认的django_migrations表

 
mark

双击django_migrations表可以看到我们migration的记录。

 
mark

会记录哪个app下的哪个initial.py已经运行了。

进入Navicat进行成功性验证:

 
mark

可以看到我们的表已经生成成功,命名规则为: app名称 + 我们的类名变成小写

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

  • 新建Python的package: apps
 
mark
  • 把四个app都拖进apps中去。
 
mark

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

解决方案:右键MarksourceRoot。根目录下找不到的,会去apps下搜索。

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

解决方案(图来源于我的DjangoGetStarted教程):

 
mark

同理,插入第0是希望它先搜索我们app下东西:

 
mark

成功性验证

 
mark
 
mark

可以看到Django已经可以正常run成功了。

第四章总结

  • 我们设计了app
 
mark
  • 设计了user models.py
 
mark
  • 循环引用
 
mark

得出我们需要创建一个更高层次的app。分层设计,operation在更高层。

  • Courses models.py
 
mark
  • organization models.py
 
mark
  • operation models.py
 
mark

通过makemigrations 生成表的变动 & migrate
每个app下的migration目录的用途,和数据库中django_migration
将所有app放到同一个目录之下。

本章结束对应commit:

数据表全部生成,migration目录&表django_migration。将app放到apps目录。对应4-9.
第四章结束!撒花。

原文学习来自简书,作者:天涯明月笙
原文链接:https://www.jianshu.com/p/7bb70e7536d7

django+xadmin在线教育平台(八)的更多相关文章

  1. django+xadmin在线教育平台(一)

    大家好,此教程为在慕学网的实战教程Python升级3.6 强力Django+杀手级Xadmin打造在线教育平台的学习笔记,不对望指正! 使用Django+Xadmin打造在线教育平台(Python2, ...

  2. django+xadmin在线教育平台(五)

    3-3 django orm介绍与model设计 上节教程完成后代码(来学习本节前置条件): 对应commit: 留言板前端页面展示.本次内容截止教程3-2结束. 可能现在你还在通过手写sql语句来操 ...

  3. django+xadmin在线教育平台(四)

    3-2 配置表单页面 必要的该说的,该了解的 前置条件: 你已经学习了前面教程.将项目的文件夹目录结构,setting配置等修改完毕与我保持一致. 本节通过Django快速的配置一个留言板页面来学习 ...

  4. django+xadmin在线教育平台(十)

    剩余app model注册 courses注册 新建courses/adminx.py: # encoding: utf-8 __author__ = 'mtianyan' __date__ = '2 ...

  5. django+xadmin在线教育平台(六)

    4-1 使用py3.6和django1.11开发系统前注意事项 直接通过Python3.6和django最新版本来开发我们的系统的一些注意事项. 原版本: Python 2.7 & djang ...

  6. django+xadmin在线教育平台(十七)

    8-1 课程列表 拷贝课程列表页到template目录 创建课程相关的urls.py Mxonline2/urls.py中声明包含到course的url中: # 课程app的url配置 url(r&q ...

  7. django+xadmin在线教育平台(十六)

    7-7 modelform 提交我要学习咨询1 对应表userask form会对字段先做验证,然后保存到数据库中. 可以看到我们的forms和我们的model中有很多内容是一样的.我们如何让代码重复 ...

  8. django+xadmin在线教育平台(十五)

    7-4 课程机构列表页数据展示2 前去html中进行数据填充   mark 可以看到所有城市是通过a标签,当前选中城市为active.   mark 之后把下面的写死的城市删除掉.   mark 这时 ...

  9. django+xadmin在线教育平台(十四)

    7-1 django templates模板继承1 机构可以筛选类别 机构可以根据所在地区进行分类 右侧我要学习功能: form表单提交 右下:授课机构排名 页面头部与底部为全局头和全局底部. Dja ...

随机推荐

  1. Emacs学习笔记1

    Emacs笔记-Emacs基本的文本操作 使用命令时要在minibuffer缓冲区中 关于文件 注意 在对单词的操作中C开头的控制范围要比M开头的控制范围要下 对于文件的撤销操作, 不要使用C-x, ...

  2. HDU5411——CRB and Puzzle——————【矩阵快速幂优化dp】

    CRB and Puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  3. 调用webservice

    WebClient web = new WebClient(); Stream stream = web.OpenRead(this._wsdlUrl); //Stream streamInfo = ...

  4. Chrome浏览器正常,IE下界面却乱了

    背景:项目实战中总会遇到一些小问题,IE特别多 Chrome浏览器页面正常,IE下界面就乱了 原因分析 1.首先想到的是代码有米有问题呢?主要指的是兼容性 2.兼容性没有问题,那我们打开IE的开发工具 ...

  5. Android打包混淆文件模板

    # This is a configuration file for ProGuard. # http://proguard.sourceforge.net/index.html#manual/usa ...

  6. u-boot分析(四)---设置异常向量表|设置SVC模式

    u-boot分析(四) 通过前三篇的分析,我们对u-boot已经有了整体的认识和掌握,但是我们仍然对于其部分硬件是如何初始化的不太清楚,所以接下来几篇博文我将会对我们在http://www.cnblo ...

  7. EF--Model First

    Model First先设计Model对象,再由对象生成数据库. 1.新建控制台项目,名称ModelFirst,确定. 2.点击选中项目,右键-->添加-->新建项目--选择数据模板--& ...

  8. TP5.1:facade静态代理

    THINKPHP中有很多很多的facade静态代理,这些静态代理的位置在:thinkphp\think\facade文件夹下 1.在app\commom中新建一个文件,名为:Test.php,表示被代 ...

  9. 二进制安装mysql5.6

    安装依赖包  yum install -y libaio yum install -y perl perl-devel       解压   mkdir /opt/mysql mv mysql-5.6 ...

  10. 制作URL以GET方式提交的简单加密程序

    首先我们用到的是 DESCryptoServiceProvider 类 对此微软给出的解释是 定义访问数据加密标准 (DES) 算法的加密服务提供程序 (CSP) 版本的包装对象.无法继承此类. 接下 ...