西游之路——python全栈——CRM项目之表结构设计

一、表结构设计

  1 from django.db import models
  2 from django.contrib.auth.models import User
  3 
  4 """自带验证"""
  5 class UserProFile(models.Model):
  6     """用户信息表"""
  7     user = models.OneToOneField(User,on_delete=models.CASCADE)
  8     name = models.CharField(max_length=32,verbose_name='姓名')
  9     role = models.ManyToManyField('Role',null=True,blank=True)
 10 
 11     class Meta:
 12         verbose_name_plural = '用户信息表'
 13 
 14     def __str__(self):  # __unicode__
 15         return self.name
 16 
 17 class Role(models.Model):
 18     """角色表"""
 19     name = models.CharField(max_length=64,unique=True)
 20     menus = models.ManyToManyField('Menus', verbose_name='菜单',blank=True)
 21 
 22     class Meta:
 23         verbose_name_plural = '角色表'
 24 
 25     def __str__(self):
 26         return self.name
 27 
 28 class CustomerInfo(models.Model):
 29     """客户信息"""
 30     name = models.CharField(max_length=32,default=None)
 31     contact_type_choices = (
 32         (0,'qq'),
 33         (1,'微信'),
 34         (2,'手机'),
 35     )
 36     contact_type = models.SmallIntegerField(choices=contact_type_choices,default=0)
 37     contact = models.CharField(max_length=64,unique=True)
 38     source_choices = (
 39         (0,'QQ群'),
 40         (1,'51CTO'),
 41         (2,'百度推广'),
 42         (3,'知乎'),
 43         (4,'转介绍'),
 44         (5,'其他'),
 45     )
 46     source = models.SmallIntegerField(choices=source_choices)
 47     referral_from = models.ForeignKey('self',null=True,blank=True,verbose_name='转介绍',on_delete=models.CASCADE)
 48 
 49     consult_courses = models.ManyToManyField('Course',verbose_name='咨询课程')
 50     consult_content = models.TextField(verbose_name='咨询内容')
 51     status_choices = (
 52         (0,'未报名'),
 53         (1,'已报名'),
 54         (2,'已退学'),
 55     )
 56     status = models.SmallIntegerField(choices=status_choices)
 57     consultant = models.ForeignKey('UserProFile',verbose_name='课程顾问',on_delete=models.CASCADE)
 58     date = models.DateField(auto_now_add=True)
 59 
 60     class Meta:
 61         verbose_name_plural = '客户信息表'
 62 
 63     def __str__(self):
 64         return self.name
 65 
 66 class Student(models.Model):
 67     """学员表"""
 68     customer = models.ForeignKey('CustomerInfo',on_delete=models.CASCADE)
 69     class_grade = models.ManyToManyField('ClassList')
 70 
 71     class Meta:
 72         verbose_name_plural = '学员表'
 73 
 74     def __str__(self):
 75         return self.customer
 76 
 77 class CustomerFollowUp(models.Model):
 78     """客户跟踪记录表"""
 79     customer = models.ForeignKey('CustomerInfo',on_delete=models.CASCADE)
 80     content = models.TextField(verbose_name='跟踪内容')
 81     user = models.ForeignKey('UserProFile',verbose_name='跟进人',on_delete=models.CASCADE)
 82     status_choices = (
 83         (0,'近期无报名计划'),
 84         (1,'一个月内报名'),
 85         (2,'2周内报名'),
 86         (3,'已报名'),
 87     )
 88     status = models.SmallIntegerField(choices=status_choices)
 89     date = models.DateField(auto_now_add=True)
 90 
 91     class Meta:
 92         verbose_name_plural = '客户跟踪记录表'
 93 
 94     def __str__(self):
 95         return self.content
 96 
 97 class Course(models.Model):
 98     """课程表"""
 99     name = models.CharField(verbose_name='课程名称',max_length=64,unique=True)
100     price = models.PositiveSmallIntegerField()   # 必须为正
101     period = models.PositiveSmallIntegerField(verbose_name='课程周期(月)',default=5)
102     outline = models.TextField(verbose_name='大纲')
103 
104     class Meta:
105         verbose_name_plural = '课程表'
106 
107     def __str__(self):
108         return self.name
109 
110 class ClassList(models.Model):
111     """班级列表"""
112     branch = models.ForeignKey('Branch',on_delete=models.CASCADE)
113     course = models.ForeignKey('Course',on_delete=models.CASCADE)
114     class_type_choices = (
115         (0,'脱产'),
116         (1,'周末'),
117         (2,'网络班')
118     )
119     class_type = models.SmallIntegerField(choices=class_type_choices)
120     semester = models.SmallIntegerField(verbose_name='学期')
121     teachers = models.ManyToManyField('UserProFile',verbose_name='讲师')
122     start_date = models.DateField('开班日期')
123     graduate_date = models.DateField('毕业日期',blank=True,null=True)
124 
125     class Meta:
126         verbose_name_plural = '班级列表'
127         unique_together = (
128             'course',
129             'semester',
130             'branch',
131             'class_type',
132         )
133 
134     def __str__(self):
135         return '%s(%s)期' %(self.course.name, self.semester)
136 
137 class CourseRecord(models.Model):
138     """上课记录"""
139     class_grade = models.ForeignKey('ClassList',verbose_name='上课班级',on_delete=models.CASCADE)
140     day_num = models.PositiveSmallIntegerField('课程节次')
141     teacher = models.ForeignKey('UserProFile',on_delete=models.CASCADE)
142     title = models.CharField('本节主题',max_length=64)
143     content = models.TextField('本节内容')
144     has_homework = models.BooleanField('本节有作业',default=True)
145     homework = models.TextField('作业需求',blank=True,null=True)
146     date = models.DateTimeField(auto_now_add=True)
147 
148     class Meta:
149         verbose_name_plural = '上课记录'
150         unique_together = (
151             'class_grade',
152             'day_num',
153         )
154 
155     def __str__(self):
156         return '%s第(%s)节' %(self.class_grade, self.day_num)
157 
158 class StudyRecord(models.Model):
159     """学习记录"""
160     course_record = models.ForeignKey('CourseRecord',on_delete=models.CASCADE)
161     student = models.ForeignKey('Student',on_delete=models.CASCADE)
162 
163     score_choices = (
164         (100,'A+'),
165         (90,'A'),
166         (85,'B+'),
167         (80,'B'),
168         (75,'B-'),
169         (70,'C+'),
170         (60,'C'),
171         (40,'C-'),
172         (-50,'D'),
173         (0,'N/A'), # not avaliable
174         (-100,'COPY'),
175     )
176     score = models.SmallIntegerField(choices=score_choices,default=0)
177     show_choices = (
178         (0,'缺勤'),
179         (1,'已签到'),
180         (2,'迟到'),
181         (3,'早退'),
182     )
183     show_status = models.SmallIntegerField(choices=show_choices)
184     note = models.TextField('成绩备注',blank=True,null=True)
185     date = models.DateTimeField(auto_now_add=True)
186 
187     class Meta:
188         verbose_name_plural = '学习记录'
189 
190     def __str__(self):
191         return '%s %s %s'  %(self.course_record,self.student,self.score)
192 
193 class Branch(models.Model):
194     """校区"""
195     name = models.CharField(max_length=64,unique=True)
196     addr = models.CharField(max_length=128,blank=True,null=True)
197 
198     class Meta:
199         verbose_name_plural = '校区'
200 
201     def __str__(self):
202         return self.name
203 
204 class Menus(models.Model):
205     """动态菜单"""
206     name = models.CharField('菜单名',max_length=32)
207     url_type_choices = (
208         (0,'absolute'),
209         (1,'dynamic'),
210     )
211     url_type = models.SmallIntegerField(choices=url_type_choices,default=0)
212     url_name = models.CharField('连接',max_length=128)
213 
214 
215     class Meta:
216         verbose_name_plural = '菜单'
217         unique_together = ('name','url_name')
218 
219     def __str__(self):
220         return self.name
Model.py

总结:

  1、防止以后掉坑,需多花心思设计表结构

  2、先整体把所有表列出,一定给表写注释

  3、在逐一完善字段,并确定个表之间的关系

  4、后续添加

  5、注意细节,变量命名的规范,单复数

  6、日后若想用Django自带验证时,用户需关联Django的User(O2O)

转载于:https://www.cnblogs.com/Lujun1028/p/9832178.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

你见过吗?9款超炫的复选框(Checkbox)效果

复选框(Checkbox)在各个浏览器中的效果不一致,因此很多 Web 开发人员会自己重新设计一套界面和使用体验都更佳的复选框功能。下面就给大家分享9款超炫的复选框(Checkbox)效果,纯 CSS3 实现,未使…

系统制成docker镜像_docker镜像原理 镜像制作 dockerfile

为什么一个centos镜像只有两百多兆,而tomcat镜像五百多兆1.先说说操作系统操作系统组成部分:进程调度子系统进程通信子系统内存管理子系统设备管理子系统文件管理子系统网络通信子系统作业控制子系统Linux文件系统由bootfs和rootfs两部分组成bootfs&…

linux的vi命令详解,Linux上Vi命令详解

Linux下Vi命令详解补充一点:在vi中使用命令的方法是:冒号命令回车,如:q 回车代表退出。这里有一本0分下载关于Vi详细介绍的书:http://download.csdn.net/detail/zqiang_55/4399731文本编辑器是所有计算机系统中最常用的一种工具。…

jpg、gif、png-8、png-24的区别

一、gif格式的特点 1、透明性。gif是一种布尔透明类型,即它可以是全透明,也可以是全不透明,但是没有半透明 2、动画。gif支持动画 3、无损耗性。gif是一种无损耗的图像格式,这意味着你可以对gif图片做任何操作也不会使图片质量产生…

Java依赖注入选项

我想花一些时间来总结一些流行的Java依赖注入(DI)框架。 这是可用功能的高级概述。 首先,什么是依赖注入? “依赖注入是一种软件设计模式,可以删除硬编码的依赖,并可以在运行时或编译时更改它们。” – 维…

实用技巧:使用 Google Analytics 跟踪 JS 错误

Google Analytics(谷歌分析)不仅仅是一个流量统计工具,你还可以用它来测量广告活动的有效性,跟踪用户多远到所需的页面流(从点击广告到购物车到结账页面)获取,并基于用户的信息设置浏览器和语言…

从Ubuntu 14.04 LTS版升级到Ubuntu 16.04 LTS

Ubuntu 16.04 (Xerial Xerus) Long Term Support版于最近发布了。要想了解它的新功能和新特性,就必须升级或安装这个新系统。 本文讲述怎样一步步从Ubuntu 14.04 LTS版升级到Ubuntu 16.04 LTS版。要注意在升级前做好重要数据的备份,以免造成数据损失。因…

finditerable 转list_java – 通过拆分和运行将ListenableFuture转换为Iterable

(替代my original answer)但是,如果转型是缓慢的,或者某些输入可能会失败但是对其他输入成功会怎么样?在这种情况下,我们希望单独转换每个输出.另外,我们希望确保转换只发生一次.我们的集合转换方法不能保证这一点.因此,在您的示例代码中,输出上的每次迭代都会向执行…

linux 的date命令详解,linux之date命令详解

时间方面 :% : 印出% %n : 下一行%t : 跳格%H : 小时(00..23)%I : 小时(01..12)%k : 小时(0..23)%l : 小时(1..12)%M : 分钟(00..59)%p : 显示本地 AM 或 PM%r : 直接显示时间 (12 小时制,格式为 hh:mm:ss [AP]M)%s : 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止…

Java 8:对集合中的值进行排序

意识到Java 8将在接下来的几周内发布其GA版本之后,我认为现在是时候来看看它了,在过去的一周里,我一直在阅读Venkat Subramaniam的书 。 我要讲的是第3章,其中涉及对人员集合进行排序。 Person类的定义大致如下: sta…

html的table弹窗_Js弹出基于Table的可关闭浮动层

可以拖动和隐藏的层,替代弹出窗口isIEdocument.all;isNN!document.all&&document.getElementById;isN4document.layers;isHotfalse;function ddInit(e){topDogisIE ? "BODY" : "HTML";whichDogisIE ? document.all.theLayer : docume…

Linux装ntfs后内存不够,Linux_安装Ubuntu后无法使用NTFS硬盘或移动硬盘,  在安装Ubuntu系统后,存在 - phpStudy...

安装Ubuntu后无法使用NTFS硬盘或移动硬盘在安装Ubuntu系统后,存在无法使用NTFS硬盘或移动硬盘的问题,下面小编就给大家介绍下Ubuntu系统无法挂载NTFS的解决方法,不知如何挂载的朋友不妨来了解下。具体问题如下图所示:“Please res…

TJOI2018Party

题目描述 小豆参加了\(NOI\)的游园会,会场上每完成一个项目就会获得一个奖章,奖章 只会是\(N\), \(O\), \(I\)的字样。在会场上他收集到了\(K\)个奖章组成的串。 兑奖规则是奖章串和兑奖串的最长公共子序列长度为小豆最后奖励的等级。 现在已知兑奖串长度…

HTML5 Dashboard – 那些让你激动的 Web 技术

HTML5 Dashboard 是一个 Mozilla 推出的项目,里面展示了最前沿的 HTML5,CSS3,JavaScript 技术。每一项技术都有简洁,在线演示以及详细的文档链接。这些技术将成为未来一段时间 Web 开发的顶尖技术,如果不想落伍的话就赶…

通过自动回复机器人学Mybatis---基础版

第1章 案例简介 介绍要实现的案例情况,后面会通过这个案例来学习 Mybatis第2章 实战第一部----黎明前的黑暗 在没有 Mybatis 的情况下,使用 Jsp Servlet Jdbc 实现案例中的一个模块开发流程1: 开发流程2: 开发流程3:…

部署到Maven中央存储库

您需要使您的Java库公开访问吗? 您的项目托管在GitHub上吗? 您是否喜欢“将所有功能都部署到Maven Central Repository”按钮的想法? 我将展示如何使用maven-release-plugin进行设置 。 源代码托管在GitHub上,因此还将描述对源代码…

Scroll Depth – 衡量页面滚动的 Google 分析插件

Scroll Depth 是一个小型的 Google Analytics(谷歌分析)插件,可以让你衡量用户在页面上滚动了多远。它可以监控 25%、50%、75% 和 100% 四个滚动点,并发送谷歌分析事件。 您还可以跟踪页面上的特定元素是否滚动到视图中。例如在博…

aws ec2时间_AWS中自动化的三大领域,以避免支付过多的云账单

AWS是全球最常用的云服务之一。 Gartner Magic Quadrant将AWS评为最大的IaaS提供商。每个可能的域都由企业使用AWS服务。 全球约有 1,000,000家公司正在使用AWS作为其IaaS提供商。从Netflix到Unilever再到Met Office,每个人都转移到AWS上的云基础架构。既然您正在阅…

linux vector 头文件,LINUX 之Vector用法

在Linux开发过程中常用到的一个功能----列表显示.如何将中心数据进行列表显示呢?这里就用到了VECTOR容器.从中心获取的数据通过VECTOR容器传输给站点程序从而实现批量数据的传输.VECTOR容器常用的函数包括以下几个1.push_back函数函数原型:void push_back(const T& x);实现…

MySQl的一些基本知识(1)

数据库优化操作&#xff1a; MySQL优化 数据库优化维度有四个: 硬件、系统配置、数据库表结构、SQL及索引 优化成本: 硬件>系统配置>数据库表结构>SQL及索引 优化效果: 硬件<系统配置<数据库表结构<SQL及索引 运行机制原理和底层架构 MySQL的查询优化&#x…