choices参数(数据库字段设计常见)

  1. """
  2. 用户表
  3. 性别
  4. 学历
  5. 工作经验
  6. 是否结婚
  7. 是否生子
  8. 客户来源
  9. ...
  10. 针对某个可以列举完全的可能性字段,我们应该如何存储
  11. 只要某个字段的可能性是可以列举完全的,那么一般情况下都会采用choices参数
  12. """

使用示例:

  1. # models.pyclass User(models.Model):
  2. username = models.CharField(max_length=32)
  3. age = models.IntegerField()
  4. # 性别
  5. gender_choices = (
  6. (1,'男'),
  7. (2,'女'),
  8. (3,'其他'),
  9. )
  10. gender = models.IntegerField(choices=gender_choices)
  11. score_choices = (
  12. ('A','优秀'),
  13. ('B','良好'),
  14. ('C','及格'),
  15. ('D','不合格'),
  16. )
  17. # 保证字段类型跟列举出来的元祖第一个数据类型一致即可
  18. score = models.CharField(choices=score_choices,null=True)
  19. """
  20. 该gender字段存的Int类型,对应gender_choices中元素的[0]类型,score存的就是Char
  21. 那么可以非常轻松的获取到数字对应的真正的内容
  22. 1.gender字段存的数字不在上述元祖列举的范围内容
  23. 2.如果在 如何获取对应的中文信息
  24. """
  25. # test.py
  26. from app01 import models
  27. # models.User.objects.create(username='jason',age=18,gender=1)
  28. # models.User.objects.create(username='egon',age=85,gender=2)
  29. # models.User.objects.create(username='tank',age=40,gender=3)
  30. # 存的时候 没有列举出来的数字也能存(范围还是按照字段类型决定)
  31. # models.User.objects.create(username='tony',age=45,gender=4)
  32. # 取
  33. # user_obj = models.User.objects.filter(pk=1).first()
  34. # print(user_obj.gender) # 数字
  35. # 只要是choices参数的字段 如果你想要获取对应信息 固定写法 get_字段名_display()
  36. # print(user_obj.get_gender_display())
  37. user_obj = models.User.objects.filter(pk=4).first()
  38. # 如果没有对应关系 那么字段是什么还是展示什么
  39. print(user_obj.get_gender_display()) # 4

补充:

实际案例:

  1. # 实际项目案例
  2. # CRM相关内部表
  3. class School(models.Model):
  4. """
  5. 校区表
  6. 如:
  7. 北京沙河校区
  8. 上海校区
  9. """
  10. title = models.CharField(verbose_name='校区名称', max_length=32)
  11. def __str__(self):
  12. return self.title
  13. class Course(models.Model):
  14. """
  15. 课程表
  16. 如:
  17. Linux基础
  18. Linux架构师
  19. Python自动化开发精英班
  20. Python自动化开发架构师班
  21. Python基础班
  22. go基础班
  23. """
  24. name = models.CharField(verbose_name='课程名称', max_length=32)
  25. def __str__(self):
  26. return self.name
  27. class Department(models.Model):
  28. """
  29. 部门表
  30. 市场部 1000
  31. 销售 1001
  32. """
  33. title = models.CharField(verbose_name='部门名称', max_length=16)
  34. code = models.IntegerField(verbose_name='部门编号', unique=True, null=False)
  35. def __str__(self):
  36. return self.title
  37. class UserInfo(models.Model):
  38. """
  39. 员工表
  40. """
  41. name = models.CharField(verbose_name='员工姓名', max_length=16)
  42. email = models.EmailField(verbose_name='邮箱', max_length=64)
  43. depart = models.ForeignKey(verbose_name='部门', to="Department",to_field="code")
  44. user=models.OneToOneField("User",default=1)
  45. def __str__(self):
  46. return self.name
  47. class ClassList(models.Model):
  48. """
  49. 班级表
  50. 如:
  51. Python全栈 面授班 5期 10000 2017-11-11 2018-5-11
  52. """
  53. school = models.ForeignKey(verbose_name='校区', to='School')
  54. course = models.ForeignKey(verbose_name='课程名称', to='Course')
  55. semester = models.IntegerField(verbose_name="班级(期)")
  56. price = models.IntegerField(verbose_name="学费")
  57. start_date = models.DateField(verbose_name="开班日期")
  58. graduate_date = models.DateField(verbose_name="结业日期", null=True, blank=True)
  59. memo = models.CharField(verbose_name='说明', max_length=256, blank=True, null=True, )
  60. teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',limit_choices_to={'depart':1002})
  61. tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo',related_name="class_list",limit_choices_to={'depart':1006})
  62. def __str__(self):
  63. return "{0}({1}期)".format(self.course.name, self.semester)
  64. class Customer(models.Model):
  65. """
  66. 客户表
  67. """
  68. qq = models.CharField(verbose_name='qq', max_length=64, unique=True, help_text='QQ号必须唯一')
  69. name = models.CharField(verbose_name='学生姓名', max_length=16)
  70. gender_choices = ((1, '男'), (2, '女'))
  71. gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choices)
  72. education_choices = (
  73. (1, '重点大学'),
  74. (2, '普通本科'),
  75. (3, '独立院校'),
  76. (4, '民办本科'),
  77. (5, '大专'),
  78. (6, '民办专科'),
  79. (7, '高中'),
  80. (8, '其他')
  81. )
  82. education = models.IntegerField(verbose_name='学历', choices=education_choices, blank=True, null=True, )
  83. graduation_school = models.CharField(verbose_name='毕业学校', max_length=64, blank=True, null=True)
  84. major = models.CharField(verbose_name='所学专业', max_length=64, blank=True, null=True)
  85. experience_choices = [
  86. (1, '在校生'),
  87. (2, '应届毕业'),
  88. (3, '半年以内'),
  89. (4, '半年至一年'),
  90. (5, '一年至三年'),
  91. (6, '三年至五年'),
  92. (7, '五年以上'),
  93. ]
  94. experience = models.IntegerField(verbose_name='工作经验', blank=True, null=True, choices=experience_choices)
  95. work_status_choices = [
  96. (1, '在职'),
  97. (2, '无业')
  98. ]
  99. work_status = models.IntegerField(verbose_name="职业状态", choices=work_status_choices, default=1, blank=True,
  100. null=True)
  101. company = models.CharField(verbose_name="目前就职公司", max_length=64, blank=True, null=True)
  102. salary = models.CharField(verbose_name="当前薪资", max_length=64, blank=True, null=True)
  103. source_choices = [
  104. (1, "qq群"),
  105. (2, "内部转介绍"),
  106. (3, "官方网站"),
  107. (4, "百度推广"),
  108. (5, "360推广"),
  109. (6, "搜狗推广"),
  110. (7, "腾讯课堂"),
  111. (8, "广点通"),
  112. (9, "高校宣讲"),
  113. (10, "渠道代理"),
  114. (11, "51cto"),
  115. (12, "智汇推"),
  116. (13, "网盟"),
  117. (14, "DSP"),
  118. (15, "SEO"),
  119. (16, "其它"),
  120. ]
  121. source = models.SmallIntegerField('客户来源', choices=source_choices, default=1)
  122. referral_from = models.ForeignKey(
  123. 'self',
  124. blank=True,
  125. null=True,
  126. verbose_name="转介绍自学员",
  127. help_text="若此客户是转介绍自内部学员,请在此处选择内部学员姓名",
  128. related_name="internal_referral"
  129. )
  130. course = models.ManyToManyField(verbose_name="咨询课程", to="Course")
  131. status_choices = [
  132. (1, "已报名"),
  133. (2, "未报名")
  134. ]
  135. status = models.IntegerField(
  136. verbose_name="状态",
  137. choices=status_choices,
  138. default=2,
  139. help_text=u"选择客户此时的状态"
  140. )
  141. consultant = models.ForeignKey(verbose_name="课程顾问", to='UserInfo', related_name='consultanter',limit_choices_to={'depart':1001})
  142. date = models.DateField(verbose_name="咨询日期", auto_now_add=True)
  143. recv_date = models.DateField(verbose_name="当前课程顾问的接单日期", null=True)
  144. last_consult_date = models.DateField(verbose_name="最后跟进日期", )
  145. def __str__(self):
  146. return self.name
  147. class ConsultRecord(models.Model):
  148. """
  149. 客户跟进记录
  150. """
  151. customer = models.ForeignKey(verbose_name="所咨询客户", to='Customer')
  152. consultant = models.ForeignKey(verbose_name="跟踪人", to='UserInfo',limit_choices_to={'depart':1001})
  153. date = models.DateField(verbose_name="跟进日期", auto_now_add=True)
  154. note = models.TextField(verbose_name="跟进内容...")
  155. def __str__(self):
  156. return self.customer.name + ":" + self.consultant.name
  157. class Student(models.Model):
  158. """
  159. 学生表(已报名)
  160. """
  161. customer = models.OneToOneField(verbose_name='客户信息', to='Customer')
  162. class_list = models.ManyToManyField(verbose_name="已报班级", to='ClassList', blank=True)
  163. emergency_contract = models.CharField(max_length=32, blank=True, null=True, verbose_name='紧急联系人')
  164. company = models.CharField(verbose_name='公司', max_length=128, blank=True, null=True)
  165. location = models.CharField(max_length=64, verbose_name='所在区域', blank=True, null=True)
  166. position = models.CharField(verbose_name='岗位', max_length=64, blank=True, null=True)
  167. salary = models.IntegerField(verbose_name='薪资', blank=True, null=True)
  168. welfare = models.CharField(verbose_name='福利', max_length=256, blank=True, null=True)
  169. date = models.DateField(verbose_name='入职时间', help_text='格式yyyy-mm-dd', blank=True, null=True)
  170. memo = models.CharField(verbose_name='备注', max_length=256, blank=True, null=True)
  171. def __str__(self):
  172. return self.customer.name
  173. class ClassStudyRecord(models.Model):
  174. """
  175. 上课记录表 (班级记录)
  176. """
  177. class_obj = models.ForeignKey(verbose_name="班级", to="ClassList")
  178. day_num = models.IntegerField(verbose_name="节次", help_text=u"此处填写第几节课或第几天课程...,必须为数字")
  179. teacher = models.ForeignKey(verbose_name="讲师", to='UserInfo',limit_choices_to={'depart':1002})
  180. date = models.DateField(verbose_name="上课日期", auto_now_add=True)
  181. course_title = models.CharField(verbose_name='本节课程标题', max_length=64, blank=True, null=True)
  182. course_memo = models.TextField(verbose_name='本节课程内容概要', blank=True, null=True)
  183. has_homework = models.BooleanField(default=True, verbose_name="本节有作业")
  184. homework_title = models.CharField(verbose_name='本节作业标题', max_length=64, blank=True, null=True)
  185. homework_memo = models.TextField(verbose_name='作业描述', max_length=500, blank=True, null=True)
  186. exam = models.TextField(verbose_name='踩分点', max_length=300, blank=True, null=True)
  187. def __str__(self):
  188. return "{0} day{1}".format(self.class_obj, self.day_num)
  189. class StudentStudyRecord(models.Model):
  190. '''
  191. 学生学习记录
  192. '''
  193. classstudyrecord = models.ForeignKey(verbose_name="第几天课程", to="ClassStudyRecord")
  194. student = models.ForeignKey(verbose_name="学员", to='Student')
  195. record_choices = (('checked', "已签到"),
  196. ('vacate', "请假"),
  197. ('late', "迟到"),
  198. ('noshow', "缺勤"),
  199. ('leave_early', "早退"),
  200. )
  201. record = models.CharField("上课纪录", choices=record_choices, default="checked", max_length=64)
  202. score_choices = ((100, 'A+'),
  203. (90, 'A'),
  204. (85, 'B+'),
  205. (80, 'B'),
  206. (70, 'B-'),
  207. (60, 'C+'),
  208. (50, 'C'),
  209. (40, 'C-'),
  210. (0, ' D'),
  211. (-1, 'N/A'),
  212. (-100, 'COPY'),
  213. (-1000, 'FAIL'),
  214. )
  215. score = models.IntegerField("本节成绩", choices=score_choices, default=-1)
  216. homework_note = models.CharField(verbose_name='作业评语', max_length=255, blank=True, null=True)
  217. note = models.CharField(verbose_name="备注", max_length=255, blank=True, null=True)
  218. homework = models.FileField(verbose_name='作业文件', blank=True, null=True, default=None)
  219. stu_memo = models.TextField(verbose_name='学员备注', blank=True, null=True)
  220. date = models.DateTimeField(verbose_name='提交作业日期', auto_now_add=True)
  221. def __str__(self):
  222. return "{0}-{1}".format(self.classstudyrecord, self.student)
  223. """
  224. chocies参数使用场景是非常广泛的
  225. """

MTV与MVC模型

  1. # MTV:Django号称是MTV模型
  2. M:models
  3. T:templates
  4. V:views
  5. # MVC:其实django本质也是MVC
  6. M:models
  7. V:views
  8. C:controller
  9. # vue框架:MVVM模型

多对多三种创建方式:

全自动:(不推荐)

  1. # 全自动:利用orm自动帮我们创建第三张关系表
  2. class Book(models.Model):
  3. name = models.CharField(max_length=32)
  4. authors = models.ManyToManyField(to='Author')
  5. class Author(models.Model):
  6. name = models.CharField(max_length=32)
  7. """
  8. 优点:代码不需要你写 非常的方便 还支持orm提供操作第三张关系表的方法...
  9. 不足之处:第三张关系表的扩展性极差(没有办法额外添加字段...)
  10. """

纯手动:(不推荐)

  1. # 纯手动
  2. class Book(models.Model):
  3. name = models.CharField(max_length=32)
  4. class Author(models.Model):
  5. name = models.CharField(max_length=32)
  6. class Book2Author(models.Model):
  7. book_id = models.ForeignKey(to='Book')
  8. author_id = models.ForeignKey(to='Author')
  9. '''
  10. 优点:第三张表完全取决于你自己进行额外的扩展
  11. 不足之处:需要写的代码较多,不能够再使用orm提供的简单的方法
  12. 不建议你用该方式
  13. '''

半自动:(推荐)

  1. # 半自动
  2. class Book(models.Model):
  3. name = models.CharField(max_length=32)
  4. authors = models.ManyToManyField(to='Author',
  5. through='Book2Author',
  6. through_fields=('book','author')
  7. )
  8. class Author(models.Model):
  9. name = models.CharField(max_length=32)
  10. # books = models.ManyToManyField(to='Book',
  11. # through='Book2Author',
  12. # through_fields=('author','book')
  13. # )
  14. class Book2Author(models.Model):
  15. book = models.ForeignKey(to='Book')
  16. author = models.ForeignKey(to='Author')
  17. # ManyToManyField字段建在查询频率多的一方
  18. # through_fields字段先后顺序
  19. 判断的本质:
  20. 通过第三张表查询对应的表 需要用到哪个字段就把哪个字段放前面
  21. 你也可以简化判断
  22. 当前表是谁 就把对应的关联字段放前面

说明:

  • 半自动在创建外键的时候,要添加两个参数,through=’关系表名‘和through_fiedls=(‘此表在关系表(第三张中间表)中字段名‘, ‘关联表在关系表中的字段名’)
  • through_fiedls中的字段顺序:第三张表通过哪个字段查询单表,就把哪个字段放在前面
  • 方法三的好处:在项目后续迭代更新中,如果有需求,可向关系表中增加

总结:

  1. # 半自动:可以使用orm的正反向查询 但是没法使用add,set,remove,clear这四个方法
  2. # 总结:你需要掌握的是全自动和半自动 为了扩展性更高 一般我们都会采用半自动(写代码要给自己留一条后路)