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