Python【day 19】:django学习--学员系统表结构设计models


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">&laquo;</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">&raquo;</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

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM