1 #models.py
2
3 # ————————01PerfectCRM基本配置ADMIN————————
4
5 from django.db import models
6 # Create your models here.
7
8 """
9 #运行 Terminal
10 # 生成 数据表
11 # python manage.py makemigrations
12 # 数据表 迁移
13 # python manage.py migrate
14 """
15
16 """01校区表"""
17 class Branch(models.Model):
18 name = models.CharField(max_length=128,unique=True) #校区名#CharField作用是保存文本,定长的变量类型
19 addr = models.CharField(max_length=128) #地址
20 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
21 return self.name #返回 #校区名
22 class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
23 verbose_name_plural = "01校区表" #verbose_name_plural给你的模型类起一个更可读的名字
24
25 """02班级表"""
26 class ClassList(models.Model):
27 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
28 branch = models.ForeignKey("Branch",on_delete=models.CASCADE)#校区 关联到 校区表
29 course = models.ForeignKey("Course",on_delete=models.CASCADE) #课程 关联到 课程表
30
31 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
32 contract = models.ForeignKey('ContractTemplate', blank=True, null=True, default=1,on_delete=models.CASCADE) # 合同表
33 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
34
35 class_type_choices = ( #上课形式
36 (0,'面授(脱产)'),
37 (1,'面授(周末)'),
38 (2,'网络班'),)
39 #PositiveSmallIntegerField正小整数 0 ~ 32767 #choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
40 class_type = models.SmallIntegerField(choices=class_type_choices)#上课形式
41
42 #PositiveSmallIntegerField正小整数 0 ~ 32767
43 semester = models.PositiveSmallIntegerField(verbose_name="学期") #课程的第几期
44
45 #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。
46 teachers = models.ManyToManyField("UserProfile") # 老师 关联到 账号表
47
48 start_date = models.DateField(verbose_name="开班日期") #DateField 日期格式 YYYY-MM-DD #verbose_name是Admin中显示的字段名称
49
50 # DateField 日期格式 YYYY-MM-DD #verbose_name是Admin中显示的字段名称 #Django可空#数据库可以为空
51 end_date = models.DateField(verbose_name="结业日期",blank=True,null=True)
52
53 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
54 return "%s %s %s" %(self.branch,self.course,self.semester) #返回 #%s格式化输出字符串 #校区#课程# 学期
55 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
56 unique_together=('branch','course','semester') #联合索引
57 verbose_name_plural = "02班级表" #verbose_name_plural给你的模型类起一个更可读的名字
58
59 """03课程表,可以报名那些课程"""
60 class Course(models.Model):
61 name = models.CharField(max_length=64,unique=True)#课程名 #CharField作用是保存文本,定长的变量类型
62 price = models.PositiveSmallIntegerField(verbose_name="学费")#学费#PositiveSmallIntegerField正小整数 0 ~ 32767
63 period = models.PositiveSmallIntegerField(verbose_name="周期(月)") #PositiveSmallIntegerField正小整数 0 ~ 32767
64 outline = models.TextField() #课程大纲 #文本类型
65 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
66 return self.name #返回 #课程名
67 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
68 verbose_name_plural = "03课程表"#verbose_name_plural给你的模型类起一个更可读的名字
69
70 '''04客户信息表'''
71 class Customer(models.Model):
72 name = models.CharField(max_length=32,blank=True,null=True)#客户名#CharField定长文本 #名字最长32 # Django可空 #数据库可以为空
73 qq = models.CharField(max_length=64,unique=True) #QQ号#CharField定长文本 #名字最长64 #唯一,不能重复
74 qq_name = models.CharField(max_length=64,blank=True,null=True)#QQ名 #CharField定长文本 #名字最长64 # Django可空 #数据库可以为空
75 phone = models.CharField(max_length=64,blank=True,null=True)#手机号 #CharField定长文本 #名字最长64 # Django可空 #数据库可以为空
76
77 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
78 id_num=models.CharField(max_length=64,blank=True,null=True,verbose_name='身份证号')#身份证号
79 email=models.EmailField(max_length=64,blank=True,null=True,verbose_name='邮箱')#email
80 sex_choices=((0,'保密'),(1,'男'),(2,'女'))
81 sex=models.SmallIntegerField(choices=sex_choices,default=0,verbose_name='性别')
82 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
83
84 # ————————53PerfectCRM实现CRM客户报名流程缴费————————
85 status_choices = ((0,'已报名'),(1,'未报名'),(2,'已退学'))
86 status = models.SmallIntegerField(choices=status_choices,default=1)#学员状态
87 # ————————53PerfectCRM实现CRM客户报名流程缴费————————
88
89
90 source_choices = ( #客户渠道来源 (内存生成)
91 (0,'转介绍'),
92 (1,'QQ群'),
93 (2,'官网'),
94 (3,'百度推广'),
95 (4,'51CTO'),
96 (5,'知乎'),
97 (6,'市场推广'),)
98 #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
99 source = models.SmallIntegerField(choices=source_choices)#客户渠道来源
100
101 #CharField定长文本#verbose_name是Admin中显示的字段名称#名字最长64 # Django可空 #数据库可以为空
102 referral_from = models.CharField(verbose_name="转介绍人qq",max_length=64,blank=True,null=True) #来自谁介绍的
103
104 #ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
105 consult_courses = models.ForeignKey("Course",verbose_name="咨询课程", on_delete=models.CASCADE) #关联到 课程表
106
107 content= models.TextField(verbose_name="咨询详情") #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
108
109 #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。
110 tags = models.ManyToManyField("Tag",blank=True)#多对多关联到 标签表
111
112 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
113 consultant = models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到 账号表
114
115 memo = models.TextField(blank=True,null=True)#备注#TextField无限制长度的文本#Django可空#数据库可以为空
116
117 #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
118 date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
119
120 def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
121 return self.qq #返回 #QQ号
122
123 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
124 verbose_name_plural = "04客户表" #verbose_name_plural给你的模型类起一个更可读的名字
125
126 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
127 #合同模版
128 class ContractTemplate(models.Model):
129 name=models.CharField('合同名称',max_length=64,unique=True)
130 template=models.TextField()
131
132 def __str__(self):
133 return self.name
134 class Meta:
135 verbose_name_plural='合同表'
136 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
137
138
139 """05客户跟进表"""
140 class CustomerFollowUp(models.Model):
141
142 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
143 customer = models.ForeignKey("Customer", on_delete=models.CASCADE)#客户名 #关联到 客户信息表
144
145 content = models.TextField(verbose_name="跟进内容")#跟进的内容#TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
146
147 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
148 consultant =models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到 账号表
149
150 intention_choices =( #报名状态
151 (0,'2周内报名'),
152 (1,'1个月内报名'),
153 (2,'近期无报名计划'),
154 (3,'已在其它机构报名'),
155 (4,'已报名'),
156 (5,'已拉黑'),)
157 #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
158 intention=models.SmallIntegerField(choices=intention_choices) #报名状态
159
160 #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
161 date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
162
163 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
164 return "<%s:%s>" %(self.customer.qq,self.intention) #返回#格式化字符串#跨表里的QQ号#报名状态
165 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
166 verbose_name_plural = "05客户跟进表"#verbose_name_plural给你的模型类起一个更可读的名字
167
168 """06学员报名信息表"""
169 class Enrollment(models.Model):
170 # ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
171 customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字 #关联到 客户信息表
172 enrolled_class = models.ForeignKey("ClassList",verbose_name="所报班级",on_delete=models.CASCADE)#关联到 班级表
173 consultant = models.ForeignKey("UserProfile",verbose_name="课程顾问",on_delete=models.CASCADE) #关联到 账号表
174
175 #BooleanField布尔值类型#default=False默认(True)不允许出现空字符#verbose_name是Admin中显示的字段名称
176 contract_agreed = models.BooleanField(default=False,verbose_name="学员已经同意合同")#学员看合同
177 contract_approved = models.BooleanField(default=False,verbose_name="合同已经审核") #谁审核
178
179 # ————————53PerfectCRM实现CRM客户报名流程缴费————————
180 Pay_cost= models.BooleanField(default=False,verbose_name="缴费") #缴费状态
181 # ————————53PerfectCRM实现CRM客户报名流程缴费————————
182
183 # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
184 date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
185
186 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
187
188 # ————————57PerfectCRM实现admin批量生成上课记录————————
189 # return "%s %s" %(self.customer,self.enrolled_class)#返回#格式化字符串#学员名字#所报班级
190 return " 学员:%s |QQ: %s |班级:%s" %(self.customer.name,self.customer,self.enrolled_class)#返回#格式化字符串#学员名字#所报班级
191 # ————————57PerfectCRM实现admin批量生成上课记录————————
192
193 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
194 unique_together = ("customer","enrolled_class")#联合索引
195 verbose_name_plural = "06学员报名信息表"#verbose_name_plural给你的模型类起一个更可读的名字
196
197 """07缴费记录表"""
198 class Payment(models.Model):
199 #ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
200 customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字 关联到 客户信息表
201 course = models.ForeignKey("Course",verbose_name="所报课程",on_delete=models.CASCADE)#关联到 课程表
202
203 #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称#默认值=500
204 amount = models.PositiveIntegerField(verbose_name="数额",default=500)#缴费数额
205
206 #ForeignKey就是表与表之间的某种约定的关系#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
207 consultant = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#缴费给谁 关联到 账号表
208
209 # ————————53PerfectCRM实现CRM客户报名流程缴费————————
210 audit_information = models.CharField(max_length=256, blank=True, null=True, verbose_name="合同审核") # 课程顾问
211 financial = models.CharField(max_length=256, blank=True, null=True, verbose_name="财务人员") # 财务人员#CharField定长文本
212 # ————————53PerfectCRM实现CRM客户报名流程缴费————————
213
214 #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
215 date=models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
216
217 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
218 return "%s %s" %(self.customer,self.amount)#返回#格式化字符串#学员名字#缴费数额
219 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
220 verbose_name_plural = "07缴费记录表"#verbose_name_plural给你的模型类起一个更可读的名字
221
222 """08每节课上课纪录表"""
223 class CourseRecord(models.Model):
224 # ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
225 from_class = models.ForeignKey("ClassList",verbose_name="班级",on_delete=models.CASCADE) #那个班级
226
227 #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称
228 day_num = models.PositiveSmallIntegerField(verbose_name="第几节(天)") #第几节课
229
230 # ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
231 teacher = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#老师是谁 关联到 账号表
232
233 #BooleanField布尔值类型#default=True默认(True)不允许出现空字符
234 has_homework = models.BooleanField(default=True) #有没有作业
235
236 # CharField定长文本#名字最长128#Django可空#数据库可以为空
237 homework_title = models.CharField(max_length=128,blank=True,null=True) #作业标题
238
239 #TextField无限制长度的文本#Django可空#数据库可以为空
240 homework_content = models.TextField(blank=True,null=True) #作业内容
241
242 #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
243 outline =models.TextField(verbose_name="本节课程大纲") #课程主要讲什么
244
245 # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
246 date = models.DateField(auto_now_add=True)#创建时间(数据库自增)
247
248 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
249 return " %s:%s" %(self.from_class,self.day_num)#返回#格式化字符串#班级#第几节(天)
250 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
251 unique_together = ("from_class","day_num") #联合索引
252 verbose_name_plural = "08每节课上课纪录表" #verbose_name_plural给你的模型类起一个更可读的名字
253
254 """09学习纪录"""
255 class StudyRecord(models.Model):
256 # ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
257 student = models.ForeignKey("Enrollment",on_delete=models.CASCADE)#学生名字 关联到 学员报名信息表
258 course_record = models.ForeignKey("CourseRecord",on_delete=models.CASCADE)#开课记录 # 关联到 每节课上课纪录表
259
260 attendance_choices = (# 本节课上课状态记录
261 (0,"已签到"),
262 (1,"迟到"),
263 (2,"缺勤"),
264 (3,"早退"),)
265 #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
266 attendance = models.SmallIntegerField(choices=attendance_choices) # 本节课上课状态记录
267
268 score_choices = (#学习成绩
269 (100,"A+"),
270 (90,"A"),
271 (85,"B+"),
272 (80,"B"),
273 (75,"B-"),
274 (70,"C+"),
275 (65,"C"),
276 (40,"C-"),
277 (-20,"D"),
278 (-50,"COPY"),
279 (0,"N/A"),)
280 #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
281 score = models.SmallIntegerField(choices=score_choices) #学习成绩
282
283 memo = models.TextField(blank=True,null=True)#TextField无限制长度的文本#Django可空#数据库可以为空
284
285 # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
286 date = models.DateField(auto_now_add=True)#创建时间(数据库自增)
287
288 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
289 return "%s %s %s" % (self.student, self.course_record, self.score)#返回#格式化字符串#学生名字#开课记录#学习成绩
290 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
291 unique_together = ('student','course_record')#联合索引#学生名字#开课记录
292 verbose_name_plural = "09学习纪录"#verbose_name_plural给你的模型类起一个更可读的名字
293
294 # ————————34PerfectCRM实现CRM自定义用户————————
295 # """10账号表"""
296 # class UserProfile(models.Model):
297 # from django.contrib.auth.models import User # 使用django内置的用户表
298 #
299 # #OneToOneField一对一 #User是django Admin里的账号表#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
300 # user = models.OneToOneField(User,on_delete=models.CASCADE)# 用户名 #创建外键,关联django用户表
301 #
302 # name = models.CharField(max_length=32) #账号名(扩展用户字段)#CharField定长文本
303 #
304 # #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。#Django可空
305 # roles = models.ManyToManyField("Role",blank=True) #角色(权限) # 双向一对多==多对多
306 #
307 # def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
308 # return self.name #返回 #账号名
309 # class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
310 # verbose_name_plural = "10账号表"#verbose_name_plural给你的模型类起一个更可读的名字
311 # ————————34PerfectCRM实现CRM自定义用户————————
312
313 # ————————34PerfectCRM实现CRM自定义用户————————
314 #10账号表,创建用户和超级用户
315 from django.contrib.auth.models import BaseUserManager
316 class UserProfileManager(BaseUserManager):
317 def create_user(self, email, name, password=None):
318 """
319 创建并保存一个用户用给定的邮件,日期
320 出生和密码。
321 """
322 if not email:#没有email 报错
323 raise ValueError('用户必须有一个电子邮件地址')
324
325 user = self.model(
326 email=self.normalize_email(email),#验证邮箱格式
327 name=name,
328 )
329 user.set_password(password)#加密
330 user.is_active = True
331 user.save(using=self._db)
332 return user
333 def create_superuser(self, email, name, password):
334 """
335 创建并保存一个超级用户具有给定邮件,日期
336 出生和密码。
337 """
338 user = self.create_user(email,
339 password=password,
340 name=name
341 )
342 user.is_active = True
343 user.is_superuser = True
344 user.save(using=self._db)
345 return user
346
347 """10账号表"""
348 """
349
350 #删除数据库
351
352 #调用objects = UserProfileManager()#创建账号 #关联这个函数
353
354 #运行 Terminal
355 # 生成 数据表
356 # python manage.py makemigrations
357 # 数据表 迁移
358 # python manage.py migrate
359 Django Admin里账号密码重置方法
360 #运行 Terminal
361 python manage.py createsuperuser
362
363 Email address: [email protected]
364 用户名 : admin
365 Password: admin123456
366 Password (again): admin123456
367 """
368 from django.contrib.auth.models import AbstractBaseUser
369 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
370 from django.utils.translation import ugettext_lazy as _ # 语言国际化
371 from django.utils.safestring import mark_safe
372 from django.contrib.auth.models import PermissionsMixin
373 # class UserProfile(AbstractBaseUser):
374 class UserProfile(AbstractBaseUser,PermissionsMixin):
375 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
376 email=models.EmailField(
377 verbose_name='邮箱账号',
378 max_length=255,
379 unique=True#唯一 #登陆账号
380 )
381 name=models.CharField(max_length=32,verbose_name='用户名')
382
383 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
384 password = models.CharField(_('password'), max_length=128, help_text=mark_safe('''<a href=\"../password/\">修改密码</a>'''))
385 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
386
387 is_active = models.BooleanField(default=True,verbose_name='合法账号')#权限#合法账号
388 is_superuser = models.BooleanField(default=False,verbose_name='超级账号') #超级账号
389 objects = UserProfileManager()#创建账号 #关联这个函数
390 USERNAME_FIELD ='email'#指定做为 #登陆账号
391 REQUIRED_FIELDS = ['name']#必填字段
392 def get_full_name(self):
393 return self.email
394 def get_short_name(self):
395 #用户确认的电子邮件地址
396 return self.email
397 def __str__(self):
398 return self.name
399 def has_perm(self,perm,obj=None):
400 #指明用户是否被认为活跃的。以反选代替删除帐号。
401 #最简单的可能的答案:是的,总是
402 return True #有效 账号
403 def has_module_perms(self, app_label):
404 #指明用户是否可以登录到这个管理站点。
405 # 最简单的可能的答案:是的,总是
406 return True #职员状态
407 @property
408 def is_staff(self):
409 '''“用户的员工吗?”'''
410 #最简单的可能的答案:所有管理员都是员工
411 return self.is_superuser#是不是超级用户状态
412 # AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表单 #settings.py
413 # ————————34PerfectCRM实现CRM自定义用户————————
414
415 """11角色表"""
416 class Role(models.Model):
417 name = models.CharField(unique=True,max_length=32)#角色名#CharField定长文本#角色名不可以重复#最长度=32字节
418 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
419 return self.name#返回 #角色名
420 class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
421 verbose_name_plural = "11角色表" #verbose_name_plural给你的模型类起一个更可读的名字
422
423 """12标签表"""
424 class Tag(models.Model):
425 name = models.CharField(max_length=64,unique=True) #标签名#CharField定长文本#最长度=64字节#不可以重复
426 def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
427 return self.name #返回 #标签名
428 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
429 verbose_name_plural = "12标签表" #verbose_name_plural给你的模型类起一个更可读的名字
430
431 # ————————01PerfectCRM基本配置ADMIN————————