10、案例-客户关系管理系统之增删改查
一、建立模型
1、导入模型
from django.db import models
2、创建学生表
class Student(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、创建学生详情表
class StudentDetail(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、创建班级表
class Grade(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、创建课程表
class Course(models.Model): # 课程表
name = models.CharField('课程名称', max_length=20)
student = models.ManyToManyField('Student', through='Enroll')
def __str__(self):
return '%s' % self.name
6、创建学生表与课程表的中间表
class Enroll(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页面视图函数
from django.shortcuts import render, redirect,reverse
from django.http import HttpResponse
from student.models import Student, Grade, StudentDetail
from django.db.models import Q
from django.core.paginator import Paginator
# Create your views here.
def index(request):
section = '学生列表'
search = request.POST.get('search', '').strip() # 接收从html的form表单传过来的参数
if search:
if search.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') # 排序
return render(request, 'student/index.html', context={
'sts': sts,
'section': section,
'search': search,
})
2、学生删除页视图
def student_delete(request, pk):
student = Student.objects.get(pk=pk) # 查询id为pk的学生
student.is_delete = True # 将is_delete标记为True,
student.save() # 保存
return redirect(reverse('student:index'))
3、学生详情页视图
def student_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) # 查询指定学生的详情
return render(request, 'student/student_detail.html', context={
'section': section,
'grades': grades,
'sts': sts,
'grade': grade,
'detail': detail,
})
4、添加页视图函数
def student_add(request):
section = '添加学生信息'
grades = Grade.objects.all() # 获取所有的班级
if request.method == 'GET':
return render(request, 'student/student_detail.html', context={
'section': section,
'grades': grades,
})
if request.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 # 表关联
)
return redirect(reverse('student:index'))
5、修改学生信息页视图函数
def student_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) # 查询指定学生的详情
if request.method == 'GET':
return render(request, 'student/student_detail.html', context={
'section': section,
'sts': sts,
'grade': grade,
'detail': detail,
})
if request.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() # 保存
return redirect(reverse('student:index'))
三、分页功能实现
1、对主页分页方法一
1.1主页的视图函数
def index(request):
section = '学生列表'
search = request.POST.get('search', '').strip() # 接收从html的form表单传过来的参数
if search:
if search.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 # 获取页面范围
return render(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中页码的设置
2、对主页分页方法二(利用包含标签)
2.1、index中的视图函数
def index(request):
section = '学生列表'
search = request.POST.get('search', '').strip() # 接收从html的form表单传过来的参数
if search:
if search.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 # 获取页面范围
return render(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
from django import template
register = template.Library()
@register.inclusion_tag('student/paginitor.html', takes_context=True)
def pagination_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到当前页
if page - num <= 0:
for i in range(1, page+1):
page_list.append(i)
else: # 左边够显示时,页码范围page-num到当前页
for i in range(page-num, page+1):
page_list.append(i)
# 2、右边 + 当前页显示的页码列表
# 2.1、右边不够显示时,页码范围当前页到total_page
if page + num >= total_page:
for i in range(page+1, total_page+1):
page_list.append(i)
# 2.2、右边够显示时,页码范围(当前页+1)到(当前页+num)
else:
for i in range(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
-
1 %} href="{% url 'student:index' %}?page={{ page|add:'-1' }}&per_page={{ per_page }}{% endif %}" aria-label="Previous">
{% for page_num in page_list %}
- {{ page_num }}
{% endfor %}
-
2.4、在index.html中导入后在对应位置引用
1、导入:{% load student_customer_tags %}
2、引用:
四、页面展示