1 创建学员系统表结构
models
#_*_coding:utf-8_*_ from django.db import models # Create your models here. # Django练习小项目:学员管理系统设计开发 # 带着项目需求学习是最有趣和效率最高的,今天就来基于下面的需求来继续学习Django # # 项目需求: # # 1.分讲师\学员\课程顾问角色, # 2.学员可以属于多个班级,学员成绩按课程分别统计 # 3.每个班级至少包含一个或多个讲师 # 4.一个学员要有状态转化的过程 ,比如未报名前,报名后,毕业老学员 # 5.客户要有咨询纪录, 后续的定期跟踪纪录也要保存 # 6.每个学员的所有上课出勤情况\学习成绩都要保存 # 7.学校可以有分校区,默认每个校区的员工只能查看和管理自己校区的学员 # 8.客户咨询要区分来源 # Create your models here. from django.core.exceptions import ValidationError from django.db import models from django.contrib.auth.models import User class_type_choices= (('online',u'网络班'), ('offline_weekend',u'面授班(周末)',), ('offline_fulltime',u'面授班(脱产)',), ) #1用户表(讲师,销售,课程顾问,学校工作人员) class UserProfile(models.Model): #UserProfile是对默认基本表User的继承和扩展 user = models.OneToOneField(User) #一对一是外键的特例,下拉框选择一次后,下次就不能再次选择 unique name = models.CharField(u"姓名",max_length=32) #UserProfile相当于用户详细表,User相当于用户基本表(djangomore默认用户表) 这2个表中name=alex只能是一对一 #在详细表中,创建一条记录是alex,对应基本表的alex;再次创建jack的时候,对应基本表就不能还是alex,必须是jack #所以用到的是一对一 def __unicode__(self): return self.name def __str__(self): return self.name class Meta: #表中文名在admin显示 verbose_name = '校内工作人员表' verbose_name_plural = "校内工作人员表" #2校区表 class School(models.Model): name = models.CharField(u"校区名称",max_length=64,unique=True) #名字 addr = models.CharField(u"地址",max_length=128) #地址 staffs = models.ManyToManyField('UserProfile',blank=True) #校区和学校工作人员UserProfile 多对多 #一个校区多个讲师 一个讲师(校长、领导)属于多个校区 def __unicode__(self): return self.name def __str__(self): return self.name class Meta: #表中文名在admin显示 verbose_name = '校区表' verbose_name_plural = "校区表" #3课程表 class Course(models.Model): name = models.CharField(u"课程名称",max_length=128,unique=True) #课程名字 python linux price = models.IntegerField(u"面授价格") #面授价格 online_price = models.IntegerField(u"网络班价格") #网络班价格 brief = models.TextField("课程简介") #参数中的"课程简介"就相当于是字段的中文别名,显示在admin页面 # brief = models.TextField() #参数中的"课程简介"就相当于是字段的中文别名,显示在admin页面 def __unicode__(self): return self.name def __str__(self): return self.name #在admin中每条记录显示课程的名字 class Meta: #表中文名在admin显示 verbose_name = '课程表' verbose_name_plural = "课程表" #4班级表 class ClassList(models.Model): course = models.ForeignKey('Course') #外键,对应另外一张表的一条记录,本表显示course_id # 班级和课程是一对多,一个课程包含多个班级(python就包含python11期、python12期) # 外键,下拉框单选课程 course_type = models.CharField(u"课程类型",choices=class_type_choices,max_length=32)#对应26行 # 非外键,下拉框单选(和外键的区别是,外键是取的另外一张表的数据,而非外键单选是取的26行元组中的数据,页面显示元组靠后的元素) semester = models.IntegerField(u"学期") #11期 12期 start_date = models.DateField(u"开班日期") #默认必选 graduate_date = models.DateField(u"结业日期",blank=True,null=True) #允许为空 teachers = models.ManyToManyField(UserProfile,verbose_name=u"讲师") #字段显示中文在admin 多对多 #一个班多个老师,一个老师带多个班 def __unicode__(self): return "%s(%s)" %(self.course.name,self.course_type) def __str__(self): # return "%s[%s](%s)" %(self.course.name,self.semester,self.course_type) #显示元组靠前的元素(offline_weekend) return "%s[%s](%s)" %(self.course.name,self.semester,self.get_course_type_display()) #显示元组靠后的元素(面授班周末) 显示汉字 get_course_type_display() 其中course_type是字段名 # 前端html也可以这么写 get_course_type_display 需要去掉小括号 class Meta: #表中文名,和字段联合惟一 verbose_name = u'班级列表' verbose_name_plural = u"班级列表" #表名显示中文在admin unique_together = ("course","course_type","semester") #课程-python 课程类型:面授班 学期:11期 这个3个字段联合惟一(不会出现2个python面授班11期) #5客户表(学生) class Customer(models.Model): qq = models.CharField(u"QQ号",max_length=64,unique=True) #qq必须有,且惟一 name = models.CharField(u"姓名",max_length=32,blank=True,null=True) #姓名可以为空,刚刚咨询的时候,一般不说真实名字 phone = models.BigIntegerField(u'手机号',blank=True,null=True) stu_id = models.CharField(u"学号",blank=True,null=True,max_length=64) #id = models.CharField(u"身份证号",blank=True,null=True,max_length=128) source_type = (('qq',u"qq群"), #学员渠道 ('referral',u"内部转介绍"), ('51cto',u"51cto"), ('agent',u"招生代理"), ('others',u"其它"), ) source = models.CharField(u'客户来源',max_length=64, choices=source_type,default='qq') referral_from = models.ForeignKey('self',verbose_name=u"转介绍自学员",help_text=u"若此客户是转介绍自内部学员,请在此处选择内部学员姓名",blank=True,null=True,related_name="internal_referral") #由谁转介绍的,介绍人也是客户表中的,自关联外键(1对多,1个介绍人介绍多个学员) # related_name="internal_referral" 是固定写法,反查用internal_referral字段 # 通过zhangxiaoyu.referral_from就可以查看张晓宇是谁推荐的(比如廖家发) # 通过介绍人廖家发,查廖家发推荐了谁,用liaojiafa.internal_referral反查到(张晓宇) course = models.ForeignKey(Course,verbose_name=u"咨询课程") #外键一对多 class_type = models.CharField(u"班级类型",max_length=64,choices=class_type_choices)#26行 customer_note = models.TextField(u"客户咨询内容详情",help_text=u"客户咨询的大概情况,客户个人信息备注等...") status_choices = (('signed',u"已报名"), ('unregistered',u"未报名"), ('graduated',u"已毕业"), ) #学员状态 status = models.CharField(u"状态",choices=status_choices,max_length=64,default=u"unregistered",help_text=u"选择客户此时的状态") consultant = models.ForeignKey(UserProfile,verbose_name=u"课程顾问") date = models.DateField(u"咨询日期",auto_now_add=True) #自动加上时间 class_list = models.ManyToManyField('ClassList',verbose_name=u"已报班级",blank=True) #可以为空,如果已经报名了,就选班级 多对多(一个班级多个学员,一个学员报了多个班--dali,下拉框多选) #创建学员的时候,选择班级,但是要查每个班级有多少人,就是个反向关联 def __unicode__(self): return "%s,%s" %(self.qq,self.name ) def __str__(self): return "%s,%s" %(self.qq,self.name ) class Meta: #表中文名在admin显示 verbose_name = '学员表' verbose_name_plural = "学员表" #6跟踪记录表 class ConsultRecord(models.Model): customer = models.ForeignKey(Customer,verbose_name=u"所咨询客户") #一对多,外键,一个学员可以有多条跟踪记录(每个跟踪记录只属于一个学员) note = models.TextField(u"跟进内容...") status_choices = ((1,u"近期无报名计划"), (2,u"2个月内报名"), (3,u"1个月内报名"), (4,u"2周内报名"), (5,u"1周内报名"), (6,u"2天内报名"), (7,u"已报名"), ) #近期的报名学习计划 status = models.IntegerField(u"状态",choices=status_choices,help_text=u"选择客户此时的状态") consultant = models.ForeignKey(UserProfile,verbose_name=u"跟踪人") #一对多,外键,一个课程顾问可以有多条跟踪记录(每个跟踪记录只属于一个课程顾问),下拉框是课程顾问(校内工作人员)的名字 date = models.DateField(u"跟进日期",auto_now_add=True) #自动添加当条记录的跟踪日期 # (第一次和课程顾问a聊的,2个月内,不管是和谁签的,都算在a上,但是过了2个月,再和课程顾问b聊的,就算在b上了) def __unicode__(self): #py2.7 return u"%s, %s" %(self.customer,self.status) def __str__(self): #py3.5 # return u"%s, %s" %(self.customer,self.status) #显示148元组的前面元素-key return u"%s, %s" %(self.customer,self.get_status_display()) #显示148元组的后面元素-value class Meta: verbose_name = u'客户咨询跟进记录' verbose_name_plural = u"客户咨询跟进记录" #7课程记录表 class CourseRecord(models.Model): course = models.ForeignKey(ClassList,verbose_name=u"班级(课程)") #外键,下拉框单选班级 内容从另外一个表取 day_num = models.IntegerField(u"节次",help_text=u"此处填写第几节课或第几天课程...,必须为数字") #day19 date = models.DateField(auto_now_add=True,verbose_name=u"上课日期") teacher = models.ForeignKey(UserProfile,verbose_name=u"讲师") #外键,下拉框单选老师,内容从校内工作人员表取-用户表 def __unicode__(self): return u"%s 第%s天" %(self.course,self.day_num) def __str__(self): return u"%s 第%s天" %(self.course,self.day_num) #control控制台 显示pythons12 day19 class Meta: verbose_name = u'上课纪录' verbose_name_plural = u"上课纪录" #表名中文显示 unique_together = ('course','day_num') #联合惟一 python面授 s12 day19不能出现2个一样的 #8学习记录表(某学员的学习记录表) class StudyRecord(models.Model): course_record = models.ForeignKey(CourseRecord, verbose_name=u"第几天课程") #外键,下拉框单选上课记录(这里不能是一对一,如果是一对一,就意味中只有1个人能来上课 vip了) student = models.ForeignKey(Customer,verbose_name=u"学员") # student = models.OneToOneField(Customer,verbose_name=u"学员") #外键,下拉框单选学员的名字 每个学员只能有一个学习记录--联合惟一 226行 record_choices = (('checked', u"已签到"), ('late',u"迟到"), ('noshow',u"缺勤"), ('leave_early',u"早退"), ) #签到记录(下拉框单选,但是区别于外键-外键是从别的表取数据) record = models.CharField(u"上课纪录",choices=record_choices,default="checked",max_length=64) score_choices = ((100, 'A+'), (90,'A'), (85,'B+'), (80,'B'), (70,'B-'), (60,'C+'), (50,'C'), (40,'C-'), (0,'D'), (-1,'N/A'), (-100,'COPY'), (-1000,'FAIL'), ) #成绩作业记录(下拉框单选,但是区别于外键-外键是从别的表取数据) score = models.IntegerField(u"本节成绩",choices=score_choices,default=-1) date = models.DateTimeField(auto_now_add=True) #自动添加日期时间 note = models.CharField(u"备注",max_length=255,blank=True,null=True) #备注可以为空 def __unicode__(self): return u"%s,学员:%s,纪录:%s, 成绩:%s" %(self.course_record,self.student.name,self.record,self.get_score_display()) #self.get_score_display()是为了显示A B+等value 而不是显示100 90分数 def __str__(self): # return u"%s,学员:%s,纪录:%s, 成绩:%s" %(self.course_record,self.student.name,self.record,self.get_score_display()) return u"%s,学员:%s,纪录:%s, 成绩:%s" %(self.course_record,self.student.name,self.get_record_display(),self.get_score_display()) class Meta: verbose_name = u'学员学习纪录' verbose_name_plural = u"学员学习纪录" #表的中文别名 unique_together = ('course_record','student') #联合唯一 例如:小宇18天只能上一次,无法在18天上2次 #student的标识是qq号码 # 学员管理系统表结构
2、admin.py
from django.contrib import admin # Register your models here. from app01 import models # class entryadmin(admin.ModelAdmin): # list_display = ("blog","headline","pub_date","mod_date","n_comments","n_pingbacks") class CourseRecordadmin(admin.ModelAdmin): #课程记录表 list_display = ("course","day_num","teacher","date") #admin显示表的字段,默认只显示1个,这里可以多显示几个字段 admin.site.register(models.UserProfile) #学校工作人员 admin.site.register(models.School) #校区 admin.site.register(models.Course) #课程表 admin.site.register(models.ClassList) #班级表 admin.site.register(models.Customer) #学员表 admin.site.register(models.ConsultRecord) #跟踪记录表 admin.site.register(models.CourseRecord,CourseRecordadmin) #课程记录表 admin.site.register(models.StudyRecord) #学习记录表 # admin.site.register(models.Entry,entryadmin)
二、用户认证
#需求1:用户认证的实现,只有用户登录了,才能看到welcome to oldboy crm,如果用户没有登录,是无法看到的
# 会自动跳转到http://127.0.0.1:8000/accounts/login/?next=/index/,显示登录框
# 在这个页面写一个登录前的页面-html,输入正确用户名和密码登录后
# 注意,如果用户已经登录admin了,说明用户已经登录了,需要先退出admin登录
#需求2:用户认证成功后,前台显示用户名
#需求3:用户退出
views
from django.shortcuts import render,HttpResponse,redirect,HttpResponseRedirect from django.contrib.auth.decorators import login_required #导入 from django.contrib.auth import authenticate,login #导入认证 # Create your views here. #需求1:用户认证的实现,只有用户登录了,才能看到welcome to oldboy crm,如果用户没有登录,是无法看到的 # 会自动跳转到http://127.0.0.1:8000/accounts/login/?next=/index/,显示登录框 # 在这个页面写一个登录前的页面-html,输入正确用户名和密码登录后 # 注意,如果用户已经登录admin了,说明用户已经登录了,需要先退出admin登录 #需求2:用户认证成功后,前台显示用户名 #需求3:用户退出--nok @login_required #装饰器,1先导入2行,2再添加这个装饰器后,就实现了需求1 def index(request): return render(request,"index.html") def acc_login(request): if request.method == "POST": #如果是post提交 print(request.POST) #<QueryDict: {'csrfmiddlewaretoken': ['YZijm5yl6wGLuaxUSr7Nfm0iuSh3PTF8'], # 'pwd': ['alex1234'], 'username': ['alex']}> user = authenticate(username=request.POST.get("username"),#获取用户输入的用户名和密码,验证后,存在user对象 password=request.POST.get("pwd")) if user is not None: #不为空,说明验证通过 login(request,user) #将用户名和密码提交登录,必须提交,否则有问题 # return HttpResponseRedirect("/index/") #跳转到http://127.0.0.1:8000/index/页面 return HttpResponseRedirect("/") #跳转到http://127.0.0.1:8000/页面 else: login_err = "wrong username or password!" #将错误信息作为第三个参数传到前端html return render(request,"acc_login.html",{"login_err":login_err}) return render(request,"acc_login.html") #如果是get
html母板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>oldboy CRM</h1> {% block page-container %} {# 可以被子模板重写 block#} <h1>welcome to oldboy crm</h1> <div> {% if request.user.is_authenticated %} <span> {# {{ request.user }}#} {# 15行这里只是显示了用户名,如何显示用户名对应的姓名?如何通过用户基础表查出用户详细表的姓名#} {# 通过user表查userprofile表 全小写 18行#} {{ request.user.userprofile.name }} </span> {% else %} <span> 登录/注册 </span> {% endif %} </div> {% endblock %} </body> </html>
{% extends "index.html" %} {#继承index模版#} {% block page-container %} {# 子模板重写#} <form action="" method="post">{% csrf_token %} 用户名:<input type="text" name="username"/> 密码:<input type="password" name="pwd"/> <input type="submit" value="登录"/> <div> {% if login_err %} {# 如果存在错误信息,将错误信息以红色字体显示在前端html#} <p style="color: red">{{ login_err }}</p> {% endif %} </div> </form> {% endblock %}
三、创建学员系统表结构和admin自定义字段
models.py
#_*_coding:utf-8_*_ from django.db import models # Create your models here. from django.core.exceptions import ValidationError from django.db import models from django.contrib.auth.models import User #导入User,django自带用户基础表 course_type_choices = (('online',u'网络班'), #元组嵌套元组,列表嵌套元组也可 ('offline_weekend',u'面授班(周末)',), ('offline_fulltime',u'面授班(脱产)',), ) #1校区表 class School(models.Model): name = models.CharField("校区名字",max_length=128,unique=True) #名字惟一 city = models.CharField("城市",max_length=64) #city是数据库字段,城市在在admin中显示的汉字别名 addr = models.CharField("地址",max_length=128) def __unicode__(self): #py2.7 return self.name def __str__(self): #py3.5 return self.name #admin中表的每条记录显示中文名字 class Meta: #admin页面,表名显示中文 verbose_name = '校区表' verbose_name_plural = "校区表" #2学校工作人员表(用户表) class UserProfile(models.Model): user = models.OneToOneField(User,verbose_name=u"用户名") #alex #用户名 外键的特殊情况(一对一),不能重复 #下拉框选了一次不能再选,或者是可以再选,保存的时候提示错误 #User是django自带的用户表(用户基本信息) UserProfile相当于用户详细信息表 #外键代表另外一个表的一条数据,一行记录 #alex在用户基本表和用户详细表都只有1个 name = models.CharField("姓名",max_length=64) #姓名 school = models.ForeignKey('School',verbose_name=u"校区") #校区 外键 下拉框单选校区 def __unicode__(self): return self.name def __str__(self): return self.name class Meta: #admin页面,表名显示中文 verbose_name = '学校工作人员表' verbose_name_plural = "学校工作人员表" #3学员表(客户表) class Customer(models.Model): qq = models.CharField(max_length=64,unique=True) #qq惟一 name = models.CharField("姓名",max_length=32,blank=True,null=True) #默认必选,这里允许不填 phone = models.BigIntegerField("手机号码",blank=True,null=True) course = models.ForeignKey('Course',verbose_name=u"课程") #外键 下拉框单选课程 外键不能直接写中文别名,需要verbose_name course_type = models.CharField("课程类型",max_length=64,choices=course_type_choices,default='offline_weekend') #9行 course_type_choices consult_memo = models.TextField("咨询备注") source_type_choices = (('qq',u"qq群"), #元组嵌套元组 列表嵌套元组 ('referral',u"内部转介绍"), ('51cto',u"51cto"), ('agent',u"招生代理"), ('others',u"其它"), ) source_type = models.CharField("学员渠道",max_length=64,choices=source_type_choices) #这个也是下拉框单选,和外键的区别是:外键取的数据是来一张表 referral_from = models.ForeignKey('self',blank=True,null=True,related_name="referraled_who",verbose_name=u"推荐人") #推荐人 related_name="referraled_who"是固定写法 外键关联到自己,因为推荐人也是学员表中的学员 status_choices = (('signed',u"已报名"), #学员状态 ('unregistered',u"未报名"), ('graduated',u"已毕业"), ('drop-off',u"退学"), ) status = models.CharField("学员状态",choices=status_choices,max_length=64) consultant = models.ForeignKey('UserProfile',verbose_name=u"课程顾问") # 外键 下拉框单选一个课程顾问 class_list = models.ManyToManyField("ClassList",blank=True,verbose_name=u"班级") #多对多 下拉框多选班级(允许多选,也可以只选择一个) date = models.DateField(u"咨询日期",auto_now_add=True) def __unicode__(self): return "%s(%s)"%(self.qq,self.name) def __str__(self): return "%s(%s)"%(self.qq,self.name) class Meta: #admin页面,表名显示中文 verbose_name = '学员表' verbose_name_plural = "学员表" #4学员跟踪记录表 class CustomerTrackRecord(models.Model): customer = models.ForeignKey(Customer,verbose_name="学员") #外键 下拉框单选学员 track_record = models.TextField(u"跟踪纪录") track_date = models.DateField("跟踪时间",auto_now_add=True) #跟踪日期,自动添加时间 follower = models.ForeignKey(UserProfile,verbose_name="跟踪人") #外键 下拉框单选跟踪人 status_choices = ((1,u"近期无报名计划"), (2,u"2个月内报名"), (3,u"1个月内报名"), (4,u"2周内报名"), (5,u"1周内报名"), (6,u"2天内报名"), (7,u"已报名"), ) status = models.IntegerField(u"状态",choices=status_choices,help_text=u"选择客户此时的状态") # status = models.IntegerField(u"状态",choices=get_status_choices_display(),help_text=u"选择客户此时的状态") #报错 def __unicode__(self): return "%s%s" % (self.customer,self.get_status_display()) def __str__(self): return "%s%s" % (self.customer,self.get_status_display()) #显示状态选择的value-中文 只在return中用get display class Meta: #admin页面,表名显示中文 verbose_name = '学员跟踪记录表' verbose_name_plural = "学员跟踪记录表" #5课程表 class Course(models.Model): name = models.CharField("课程名字",max_length=64,unique=True) #惟一 online_price = models.IntegerField("网络班价格") offline_price = models.IntegerField("面授班价格") introduction = models.TextField("课程说明") def __unicode__(self): return self.name def __str__(self): return self.name class Meta: #admin页面,表名显示中文 verbose_name = '课程表' verbose_name_plural = "课程表" #6班级表 class ClassList(models.Model): course = models.ForeignKey(Course,verbose_name=u"课程") #外键 下拉框单选课程 semester = models.IntegerField(verbose_name=u"学期") course_type = models.CharField("课程类型",max_length=64,choices=course_type_choices,default='offline_weekend') #9行 teachers = models.ManyToManyField(UserProfile,verbose_name=u"讲师") #多对多 下拉框多选讲师 不能显示在admin的自定义 start_date = models.DateField("开班日期") graduate_date = models.DateField("毕业日期") def __unicode__(self): return "%s(%s)(%s)" %(self.course.name,self.get_course_type_display(),self.semester) def __str__(self): #get display 显示value 而不是key return "%s(%s)(%s)" %(self.course.name,self.get_course_type_display(),self.semester) class Meta: verbose_name = '班级表' verbose_name_plural = "班级表" unique_together = ('course','semester','course_type') #联合惟一 课程+学期+类型相同就提示错误 #7上课记录表 class CourseRecord(models.Model): class_obj = models.ForeignKey(ClassList,verbose_name="班级") #外键 下拉框单选班级 day_num = models.IntegerField(u"第几节课") course_date = models.DateField(auto_now_add=True,verbose_name=u"上课时间") teacher = models.ForeignKey(UserProfile,verbose_name="讲师") #多对多 下拉框多选讲师 #students = models.ManyToManyField(Customer) def __unicode__(self): return "%s[%s]"%(self.class_obj,self.day_num) def __str__(self): return "%s[%s]"%(self.class_obj,self.day_num) class Meta: verbose_name = '上课记录表' verbose_name_plural = "上课记录表" unique_together = ('class_obj','day_num') #联合惟一 班级和第几节课都相同就报错(创建记录的时候) #8学习记录表(考勤、作业成绩) class StudyRecord(models.Model): course_record = models.ForeignKey(CourseRecord,verbose_name="上课记录") #外键 下拉框单选上课记录 student = models.ForeignKey(Customer,verbose_name="学员") #外键 下拉框单选学员 record_choices = (('checked', u"已签到"), ('late',u"迟到"), ('noshow',u"缺勤"), ('leave_early',u"早退"), ) record = models.CharField(u"签到状态", choices=record_choices,max_length=64) score_choices = ((100, 'A+'), (90,'A'), (85,'B+'), (80,'B'), (70,'B-'), (60,'C+'), (50,'C'), (40,'C-'), (0,'D'), (-1,'N/A'), (-100,'COPY'), (-1000,'FAIL'), ) score = models.IntegerField(u"本节成绩",choices=score_choices,default=-1) date = models.DateTimeField("日期",auto_now_add=True) note = models.CharField(u"备注",max_length=255,blank=True,null=True) def __unicode__(self): return "%s,%s,%s"%(self.course_record,self.student,self.record) def __str__(self): # return "%s,%s,%s"%(self.course_record,self.student,self.record) return "%s,%s,%s"%(self.course_record,self.student,self.get_record_display()) class Meta: verbose_name = '学习记录表' verbose_name_plural = "学习记录表"
admin.py
from django.contrib import admin # Register your models here. from app01 import models # class entryadmin(admin.ModelAdmin): # list_display = ("blog","headline","pub_date","mod_date","n_comments","n_pingbacks") class schooladmin(admin.ModelAdmin): #admin页面显示校区表的每个字段 list_display = ("name","city","addr") class UserProfileadmin(admin.ModelAdmin): #admin页面显示学校工作人员表-用户表的每个字段 list_display = ("name","user","school") class Customeradmin(admin.ModelAdmin): #admin页面显示学员表-客户表的某些典型字段 多对多不能写在这里 list_display = ("qq","name","course","course_type","source_type","referral_from","status","consultant") class CustomerTrackRecordadmin(admin.ModelAdmin): #admin页面显示客户跟踪记录表的某些典型字段 list_display = ("customer","track_date","follower","status") class Courseadmin(admin.ModelAdmin): #admin页面显示课程表的全部字段 list_display = ("name","online_price","offline_price","introduction") class ClassListadmin(admin.ModelAdmin): #admin页面显示班级表的全部字段 多对多不能写在这里,否则报错 list_display = ("course","semester","course_type","start_date","graduate_date") class CourseRecordadmin(admin.ModelAdmin): #admin页面显示上课记录表的全部字段 多对多不能写在这里,否则报错 list_display = ("class_obj","day_num","course_date") class StudyRecordadmin(admin.ModelAdmin): #admin页面显示学习记录表的全部字段 多对多不能写在这里,否则报错 list_display = ("course_record","student","record","score","date","note") admin.site.register(models.School,schooladmin) #自定义字段 注册后生效 9行 admin.site.register(models.UserProfile,UserProfileadmin) admin.site.register(models.Customer,Customeradmin) admin.site.register(models.CustomerTrackRecord,CustomerTrackRecordadmin) admin.site.register(models.Course,Courseadmin) admin.site.register(models.ClassList,ClassListadmin) admin.site.register(models.CourseRecord,CourseRecordadmin) admin.site.register(models.StudyRecord,StudyRecordadmin)
四、#需求1:将客户表的数据展示到前端(注意不能用admin,采用bootstrap布局+表格的形式 展示数据)
#需求2:将客户表中报名字段区分不同的颜色,高亮显示 custom.html的42行
# 1css中设置自定义的custom.css 2导入到base.html 3class="{{ item.status }
#需求3:给客户列表添加分页的功能-简单的
#需求4:分页优化-默认显示5页(取绝对值,差绝对值小于等于2,就显示)--baidu
# 前一页,后一页来翻页,到了最后一页,右箭头隐藏,到了第一页,左箭头隐藏
# 模版不支持abs吗,就需要simpletag自定义abs函数,自定义函数就实现了前端的html,再load
1、urls
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'Administrator' from django.conf.urls import url,include from django.contrib import admin from app01 import views urlpatterns = [ url(r'^$', views.dashboard), #app01下都指向dashboard http://127.0.0.1:8000/app01/ url(r'^customers/$', views.customers), # url(r'^Custompager/$', views.Custompager), ]
2、views.py
from django.shortcuts import render from app01 import models from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger #导入用于分页 # Create your views here. #需求1:将客户表的数据展示到前端(注意不能用admin,采用bootstrap布局+表格的形式 展示数据) #需求2:将客户表中报名字段区分不同的颜色,高亮显示 custom.html的42行 # 1css中设置自定义的custom.css 2导入到base.html 3class="{{ item.status } #需求3:给客户列表添加分页的功能-简单的 #需求4:分页优化-默认显示5页(取绝对值,差绝对值小于等于2,就显示)--baidu # 前一页,后一页来翻页,到了最后一页,右箭头隐藏,到了第一页,左箭头隐藏 # 模版不支持abs,就需要simpletag自定义abs函数,自定义函数就实现了前端的html,再load def dashboard(request): return render(request,"app01/dashboard.html") def customers(request): #带分页 customer_list = models.Customer.objects.all() #获取学员表-客户表的所有记录 # print(customer_list) paginator = Paginator(customer_list,1) #生成1个分页的实例,设置每页有几条数据 这里是指每页1条数据 page = request.GET.get("page") #获取前端的请求 try: customer_objs = paginator.page(page) except PageNotAnInteger: #如果输入的页码不是数字,那么返回第一页 (首次打开,返回第一页) customer_objs = paginator.page(1) except EmptyPage: #如果输入的页码超出页码范围(例如,一共是3页,输入的是5),就返回最后一页 customer_objs = paginator.page(paginator.num_pages) #num_pages指页码总数 # return render(request,"app01/custom.html",{"customer_list":customer_list}) return render(request,"app01/custom.html",{"customer_list":customer_objs}) # def customers1(request): # customer_list1 = models.Customer.objects.all() # return render(request,"app01/custom.html",{"customer_list":customer_list1})
3、custom.html
{% extends "base.html" %} {% load custom_tags %} {#加载自定义的函数--simpletags#} {% block header %} old boy crm {% endblock %} {% block content %} {# {{ customer_list }}#} 客户信息列表 {% endblock %} {% block content-page %} {# {{ customer_list }}#} {# haha22#} <table class="table table-hover"> {# http://v3.bootcss.com/css/#tables 布局(起步)和表格(全局css样式)直接在bootstrap3中找#} <thead> <tr> <th>ID</th> <th>QQ</th> <th>姓名</th> <th>渠道</th> <th>咨询课程</th> <th>课程类型</th> <th>客户备注</th> <th>状态</th> <th>课程顾问</th> <th>日期</th> </tr> </thead> <tbody> {% for item in customer_list %} <tr> <td>{{ item.id }}</td> <td>{{ item.qq }}</td> <td>{{ item.name }}</td> <td>{{ item.source_type }}</td> <td>{{ item.course }}</td> <td>{{ item.get_course_type_display }}</td> {# 取value的值 get display#} <td>{{ item.consult_memo|truncatechars:10 }}</td> {# 备注取前10个字符#} {# <td class="{{ item.status }}">{{ item.get_status_display }}</td>#} {# 取value的值 get display 1css中设置自定义的custom.css 2导入到base.html 3class="{{ item.status }}#} {# 根据不同的状态,设置不同的颜色#} <td class="{{ item.status }}">{{ item.status|alex_upper }}</td> {# 取的是key,将状态key的字母全部转换成大写 |alex_upper 这里的alex_upper是自定义函数名 注意生效需要手动重启#} {# 将item.status作为参数传到函数alex_upper 只传入了1个参数#} <td>{{ item.consultant }}</td> <td>{{ item.date }}</td> </tr> {% endfor %} </tbody> </table> <div class="pagination"> {# 分页优化版,从bootstrap找的,进行修改#} <nav> <ul class="pagination"> {% if customer_list.has_previous %} <li class=""><a href="?page={{ customer_list.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">«</span></a></li> {% endif %} {# 左箭头 前一页 判断有没有上一页#} {% for i in customer_list.paginator.page_range %} {# 遍历让每一页都显示#} {% guess_page customer_list.number i %} {# 这个语句调用自定义的simple_tags 如果很多页面都需要分页 就服用simple_tags#} {# 考虑在后台simpl_tags中返回html元素 customer_list.number 拼写#} {# {% if i == customer_list.number %}#} {# 当前页,高亮显示#} {# <li class="active"><a href="?page={{ i }}">{{ i }} </a></li>#} {# {% else %}#} {# 非当前页,取消高亮显示#} {# <li class=""><a href="?page={{ i }}">{{ i }} </a></li>#} {# {% endif %}#} {% endfor %} {# 页码#} {% if customer_list.has_next %} <li class=""><a href="?page={{ customer_list.next_page_number }}" aria-label="next"><span aria-hidden="true">»</span></a></li> {# 右箭头 后一页 判断有没有下一页 没有下一页,就不显示右箭头#} {% endif %} </ul> </nav> {# 分页简易版#} <span class="step-links"> {% if customer_list.has_previous %} <a href="?page={{ customer_list.previous_page_number }}">previous</a> {% endif %} {# 分页的前端代码,前一页#} <span class="current"> Page {{ customer_list.number }} of {{ customer_list.paginator.num_pages }}. </span> {# 当前页 page 当前页 of 总页码#} {% if customer_list.has_next %} <a href="?page={{ customer_list.next_page_number }}">next</a> {% endif %} {# 下一页#} </span> </div> {% endblock %}
4、simple_tags(custom_tags)
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'Administrator' #自定义标签语法,用于转换成大小写 from django import template #导入 from django.utils.html import format_html #用这个将后端return的字符串转换成html register = template.Library() #注册到语法库 @register.filter #装饰器 def alex_lower(value): #转换成小写 只能传入一个参数 return value.lower() @register.filter def alex_upper(value): #转换成大写 print("alex_upper",value) #alex_upper unregistered return value.upper() @register.simple_tag def guess_page(current_page,loop_num): #simple_tag 可以传入2个参数 # {% if i == customer_list.number %} # {# 当前页,高亮显示#} # <li class="active"><a href="?page={{ i }}">{{ i }} </a></li> # {% else %} # {# 非当前页,取消高亮显示#} # <li class=""><a href="?page={{ i }}">{{ i }} </a></li> # {% endif %} #翻译成后端的python语言 offset = abs(current_page-loop_num) if offset <=1: #判断显示3页,前后各1页,3页之外的不显示 if current_page == loop_num: #当前页高亮 page_ele = """<li class="active"><a href="?page=%s">%s</a></li>""" % (loop_num,loop_num) # 3引号的位置 loop_num 拼写 else: #非当前页不高亮 page_ele = """<li class=""><a href="?page=%s">%s</a></li>""" % (loop_num,loop_num) return format_html(page_ele) #后端return的字符串转换成html # return page_ele else: return "" #去掉前端的None