第10节、案例-客户关系管理系统之增删改查笔记

第10节、案例-客户关系管理系统之增删改查笔记

一、建立模型

1、导入模型

fromdjango.dbimportmodels

2、创建学生表

classStudent(models.Model):# 学生表

name=models.CharField(max_length=20)

age=models.SmallIntegerField()

sex=models.SmallIntegerField(default=1)

qq=models.CharField(max_length=20,unique=True)

phone=models.CharField(max_length=20,unique=True)

c_time=models.DateTimeField(verbose_name='创建时间',auto_now_add=True)

e_time=models.DateTimeField(verbose_name='修改时间',auto_now=True)

grade=models.ForeignKey('Grade',on_delete=models.SET_NULL,null=True)

is_delete=models.BooleanField(default=False)# 一般实际开发过程中,我们不会直接删除数据,而是给数据加上is_delete字段,来标记数据的状态。

def__str__(self):

return'%s-%s-%s'%(self.name,self.age,self.sex)

3、创建学生详情表

classStudentDetail(models.Model):#学生详情表

num=models.CharField('身份证',max_length=40,unique=True)

college=models.CharField('毕业学校',max_length=20,default='')

student=models.OneToOneField('Student',on_delete=models.CASCADE,related_name='detail')

def__str__(self):

return'%s-%s'%(self.num,self.college)

4、创建班级表

classGrade(models.Model):# 班级表

name=models.CharField('班级名称',max_length=20)

num=models.CharField('班期',max_length=20)

def__str__(self):

return'%s-%s'%(self.name,self.num)

5、创建课程表

classCourse(models.Model):# 课程表

name=models.CharField('课程名称',max_length=20)

student=models.ManyToManyField('Student',through='Enroll')

def__str__(self):

return'%s'%self.name

6、创建学生表与课程表的中间表

classEnroll(models.Model):# 课程与学生多对多中间表

student=models.ForeignKey('Student',on_delete=models.CASCADE)

course=models.ForeignKey('Course',on_delete=models.CASCADE)

pay=models.FloatField('缴费金额',default=0)

c_time=models.DateTimeField(verbose_name='创建时间',auto_now_add=True)

def__str__(self):

return'%s'%self.pay

##

二、增删改查功能实现

1、index页面视图函数

fromdjango.shortcutsimportrender,redirect,reverse

fromdjango.httpimportHttpResponse

fromstudent.modelsimportStudent,Grade,StudentDetail

fromdjango.db.modelsimportQ

fromdjango.core.paginatorimportPaginator

# Create your views here.

defindex(request):

section='学生列表'

search=request.POST.get('search','').strip()# 接收从html的form表单传过来的参数

ifsearch:

ifsearch.isdigit():# 如果是数值类型则

sts=Student.objects.filter(Q(qq=search)|Q(phone=search),is_delete=False)# 用qq和phone去匹配

else:# 如果是字符型

sts=Student.objects.filter(name=search,is_delete=False)# 则和名字匹配

else:# search都没有匹配到则查询所有学生

sts=Student.objects.filter(is_delete=False)

sts=sts.order_by('-c_time')# 排序

returnrender(request,'student/index.html',context={

'sts':sts,

'section':section,

'search':search,

    })

2、学生删除页视图

defstudent_delete(request,pk):

student=Student.objects.get(pk=pk)# 查询id为pk的学生

student.is_delete=True# 将is_delete标记为True,

student.save()# 保存

returnredirect(reverse('student:index'))

3、学生详情页视图

defstudent_detail(request,pk):

section='学生详情'

grades=Grade.objects.all()# 查询所有班级

sts=Student.objects.get(pk=pk)# 获取当前id为pk的学生信息

grade=Grade.objects.get(pk=sts.grade_id)# 查询指定学生的班级

detail=StudentDetail.objects.get(student=sts)# 查询指定学生的详情

returnrender(request,'student/student_detail.html',context={

'section':section,

'grades':grades,

'sts':sts,

'grade':grade,

'detail':detail,

    })

4、添加页视图函数

defstudent_add(request):

section='添加学生信息'

grades=Grade.objects.all()# 获取所有的班级

ifrequest.method=='GET':

returnrender(request,'student/student_detail.html',context={

'section':section,

'grades':grades,

        })

ifrequest.method=='POST':

# 获取班级信息

grade_id=request.POST.get('grade')# 获取前端传回来的grade.id

try:

grade=Grade.objects.get(pk=grade_id)

except:

grade=None

# 获取学生信息姓名、年龄、性别、qq、电话

data= {

'name':request.POST.get('name'),

'age':request.POST.get('age'),

'sex':request.POST.get('sex'),

'qq':request.POST.get('qq'),

'phone':request.POST.get('phone'),

'grade':grade#表关联,在student中

        }

student=Student.objects.create(**data)

# 获取学生详情信息

StudentDetail.objects.create(

num=request.POST.get('num'),

college=request.POST.get('college'),

student=student# 表关联

        )

returnredirect(reverse('student:index'))

5、修改学生信息页视图函数

defstudent_edit(request,pk):

section='修改学生信息'

sts=Student.objects.get(pk=pk)# 查询id为pk的学生

grade=Grade.objects.get(pk=sts.grade_id)# 查询指定学生的班级

detail=StudentDetail.objects.get(student=sts)# 查询指定学生的详情

ifrequest.method=='GET':

returnrender(request,'student/student_detail.html',context={

'section':section,

'sts':sts,

'grade':grade,

'detail':detail,

        })

ifrequest.method=='POST':

# 获取班级信息

grade_id=request.POST.get('grade')# 获取前端传回来的grade

try:

grade=Grade.objects.get(pk=grade_id)# 获取学生的班级

except:

grade=None

# 获取学生信息并修改

student=Student.objects.get(pk=pk)

student.name=request.POST.get('name')

student.age=request.POST.get('age')

student.sex=request.POST.get('sex')

student.qq=request.POST.get('qq')

student.phone=request.POST.get('phone')

student.grade=grade# 表关联

# 获取学生详情

try:

detail=student.detail# 表关联,关联表在student

except:

detail=StudentDetail()

detail.student=student# 表关联,关联表在detail

detail.num=request.POST.get('num')

detail.college=request.POST.get('college')

detail.save()# 保存

student.save()# 保存

returnredirect(reverse('student:index'))

三、分页功能实现

1、对主页分页方法一

1.1主页的视图函数

defindex(request):

section='学生列表'

search=request.POST.get('search','').strip()# 接收从html的form表单传过来的参数

ifsearch:

ifsearch.isdigit():# 如果是数值类型则

sts=Student.objects.filter(Q(qq=search)|Q(phone=search),is_delete=False)# 用qq和phone去匹配

else:# 如果是字符型

sts=Student.objects.filter(name=search,is_delete=False)# 则和名字匹配

else:# search都没有匹配到则查询所有学生

sts=Student.objects.filter(is_delete=False)

sts=sts.order_by('-c_time')# 排序

# 分页

total_num=sts.count()# 总的数据量

per_page=int(request.GET.get('per_page',5))# 每页默认条数为5

page=int(request.GET.get('page',1))# 当前页面默认为第1页

p=Paginator(sts,per_page,allow_empty_first_page=True)

sts=p.get_page(page)# 每页显示的数据

total_page=p.num_pages# 总的页面数

page_list=p.page_range# 获取页面范围

returnrender(request,'student/index.html',context={

'sts':sts,

'section':section,

'search':search,

'total_num':total_num,

'total_page':total_page,

'page':page,

'per_page':per_page,

'page_list':page_list,

    })

1.2、html中页码的设置

<navaria-label="Page navigation"style="display: inline-block">

<ulclass="pagination">

<li{%ifpage==1%}class="disabled"{%endif%}>

<ahref="{% if page > 1 %}{% url 'student:index' %}?page={{ page|add:-1 }}&per_page={{ per_page }}{% else %}{% url 'student:index' %}?page={{ page }}&per_page={{ per_page }}{% endif %}"aria-label="Previous">

<spanaria-hidden="true">上一页</span>

</a>

</li>

            {% for i in page_list %}

<li{%ifpage==i%}class="active"{%endif%}><ahref="{{ request.path }}?page={{ i }}&per_page={{ per_page }}">{{ i }}</a></li>

            {% endfor %}

<li{%ifpage==total_page%}class="disabled"{%endif%}>

<ahref="{% if page < total_page %}{% url 'student:index' %}?page={{ page|add:1 }}&per_page={{ per_page }}{% else %}{% url 'student:index' %}?page={{ page }}&per_page={{ per_page }}{% endif %}"aria-label="Next">

<spanaria-hidden="true">下一页</span>

</a>

</li>

</ul>

</nav>

<!-- Single button -->

<divclass="btn-group"style="display: inline-block; margin-top: -68px">

<buttontype="button"class="btn btn-default dropdown-toggle"data-toggle="dropdown"aria-haspopup="true"aria-expanded="false">

{{ per_page }}条/页<spanclass="caret"></span>

</button>

<ulclass="dropdown-menu">

<li><ahref="{% url 'student:index' %}?page={{ page}}&per_page= 5 ">5条/页</a></li>

<li><ahref="{% url 'student:index' %}?page={{ page}}&per_page= 10 ">10条/页</a></li>

<li><ahref="{% url 'student:index' %}?page={{ page}}&per_page= 15 ">15条/页</a></li>

<li><ahref="{% url 'student:index' %}?page={{ page}}&per_page= 20 ">20条/页</a></li>

</ul>

</div>

2、对主页分页方法二(利用包含标签)

2.1、index中的视图函数

defindex(request):

section='学生列表'

search=request.POST.get('search','').strip()# 接收从html的form表单传过来的参数

ifsearch:

ifsearch.isdigit():# 如果是数值类型则

sts=Student.objects.filter(Q(qq=search)|Q(phone=search),is_delete=False)# 用qq和phone去匹配

else:# 如果是字符型

sts=Student.objects.filter(name=search,is_delete=False)# 则和名字匹配

else:# search都没有匹配到则查询所有学生

sts=Student.objects.filter(is_delete=False)

sts=sts.order_by('-c_time')# 排序

# 分页

total_num=sts.count()# 总的数据量

per_page=int(request.GET.get('per_page',5))# 每页默认条数为5

page=int(request.GET.get('page',1))# 当前页面默认为第1页

p=Paginator(sts,per_page,allow_empty_first_page=True)

sts=p.get_page(page)# 每页显示的数据

total_page=p.num_pages# 总的页面数

page_list=p.page_range# 获取页面范围

returnrender(request,'student/index.html',context={

'sts':sts,

'section':section,

'search':search,

'total_num':total_num,

'total_page':total_page,

'page':page,

'per_page':per_page,

'page_list':page_list,

    })

2.2、在templatetags文件夹中创建student_custormer_tags.py

#!/usr/bin/python

# -*- coding: utf-8 -*-

# author:cyb time:2019/5/25 23:34

fromdjangoimporttemplate

register=template.Library()

@register.inclusion_tag('student/paginitor.html',takes_context=True)

defpagination_html(context):# 谁引用就导入谁的context

total_page=context['total_page']# 总的页面数

page=context['page']# 显示第几页的数据

page_list=context['page_list']# 页面范围

per_page=context['per_page']# 每页条数

'''

    假设现在total_page = 6

    两种页码控制方法:

    当num = 1 # 当前页面左右各有几页

    上一页  1  2  3 下一页

    上一页  4  5  6 下一页

    上一页    1  2 下一页

    上一页  5  6    下一页


    当num = 2 # 当前页面左右各有几页

    上一页        1  2  3 下一页

    上一页    1  2  3  4 下一页

    上一页  1  2  3  4  5 下一页

    上一页  2  3  4  5  6 下一页

    上一页  4  5  6      下一页


    '''

page_list= []

num=2

# 1、左边 + 当前页显示的页码列表

# 1.1、左边不够显示时,页码范围1到当前页

ifpage-num<=0:

foriinrange(1,page+1):

page_list.append(i)

else:# 左边够显示时,页码范围page-num到当前页

foriinrange(page-num,page+1):

page_list.append(i)

# 2、右边 + 当前页显示的页码列表

# 2.1、右边不够显示时,页码范围当前页到total_page

ifpage+num>=total_page:

foriinrange(page+1,total_page+1):

page_list.append(i)

# 2.2、右边够显示时,页码范围(当前页+1)到(当前页+num)

else:

foriinrange(page+1,page+num):

page_list.append(i)

return{

'total_page':total_page,

'page':page,

'page_list':page_list,

'per_page':per_page

    }

2.3、在app中新建一个包含标签渲染模板paginitor.html

<ulclass="pagination">

<li{%ifpage==1%}class="disabled"{%endif%}>

<a{%ifpage>1 %} href="{% url 'student:index' %}?page={{ page|add:'-1' }}&per_page={{ per_page }}{% endif %}" aria-label="Previous">

<spanaria-hidden="true">«</span>

</a>

</li>

    {% for page_num in page_list %}

<li{%ifpage_num==page%}class="active"{%endif%}><ahref="{{ request.path }}?page={{ page_num }}&per_page={{ per_page }}">{{ page_num }}</a></li>

    {% endfor %}

<li{%ifpage==total_page%}class="disabled"{%endif%}>

<a{%ifpage< total_page %} href="{{ request.path }}?page={{ page|add:'1' }}&per_page={{ per_page }}{% endif %}" aria-label="Next">

<spanaria-hidden="true">»</span>

</a>

</li>

</ul>

2.4、在index.html中导入后在对应位置引用

1、导入:{% load student_customer_tags %}

2、引用:

<nav aria-label="Page navigation" style="display: inline-block">

        {% pagination_html %}

</nav>

四、页面展示

1、主页展示


2、添加页展示


3、修改页展示


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352