简易的学生管理系统框架

base.html代码

  • 在http://www.bootcss.com/找模板和渲染

      {% load static %}
      <!DOCTYPE html>
      <html lang="zh-CN">
        <head>
          <meta charset="utf-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <meta name="description" content="">
          <meta name="author" content="">
          <title>{% block title %}Dashboard Template for Bootstrap{% endblock %}</title>
          <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
      	<link href="{% static 'students/css/base.css' %}" rel="stylesheet">
            <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
            <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
        </head>
        <body>
          <nav class="navbar navbar-inverse navbar-fixed-top">
            <div class="container-fluid">
              <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                  <span class="sr-only">Toggle navigation</span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">CRM管理系统</a>
              </div>
              <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav navbar-right">
                  <li><a href="#">后台</a></li>
                  <li><a href="#">论坛</a></li>
                  <li><a href="#">学员</a></li>
                  <li><a href="#">退出</a></li>
                </ul>
              </div>
            </div>
          </nav>
          <div class="container-fluid">
            <div class="row">
              <div class="col-sm-3 col-md-2 sidebar">
                <ul class="nav nav-sidebar">
                  <li class="active"><a href="#">学生管理 <span class="sr-only">(current)</span></a></li>
                  <li><a href="#">订单管理</a></li>
                  <li><a href="#">课程管理</a></li>
                  <li><a href="#">班级管理</a></li>
                </ul>
                <ul class="nav nav-sidebar">
                  <li><a href="">系统设置</a></li>
                  <li><a href="">菜单管理</a></li>
                  <li><a href="">权限管理</a></li>
                </ul>
              </div>
              <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
                  <h2 class="sub-header">{%block section %}Section title{% endblock %}</h2>
                  {% block content %}
                <div class="table-responsive">
                  <table class="table table-striped">
                    <thead>
                      <tr>
                        <th>#</th>
                        <th>Header</th>
                        <th>Header</th>
                        <th>Header</th>
                        <th>Header</th>
                      </tr>
                    </thead>
                    <tbody>
                      <tr>
                        <td>1,001</td>
                        <td>Lorem</td>
                        <td>ipsum</td>
                        <td>dolor</td>
                        <td>sit</td>
                      </tr>
                      <tr>
                        <td>1,002</td>
                        <td>amet</td>
                        <td>consectetur</td>
                        <td>adipiscing</td>
                        <td>elit</td>
                      </tr>
                      <tr>
                        <td>1,003</td>
                        <td>Integer</td>
                        <td>nec</td>
                        <td>odio</td>
                        <td>Praesent</td>
                      </tr>
                      <tr>
                        <td>1,003</td>
                        <td>libero</td>
                        <td>Sed</td>
                        <td>cursus</td>
                        <td>ante</td>
                      </tr>
                      <tr>
                        <td>1,004</td>
                        <td>dapibus</td>
                        <td>diam</td>
                        <td>Sed</td>
                        <td>nisi</td>
                      </tr>
                      <tr>
                        <td>1,005</td>
                        <td>Nulla</td>
                        <td>quis</td>
                        <td>sem</td>
                        <td>at</td>
                      </tr>
                      <tr>
                        <td>1,006</td>
                        <td>nibh</td>
                        <td>elementum</td>
                        <td>imperdiet</td>
                        <td>Duis</td>
                      </tr>
                      <tr>
                        <td>1,007</td>
                        <td>sagittis</td>
                        <td>ipsum</td>
                        <td>Praesent</td>
                        <td>mauris</td>
                      </tr>
                      <tr>
                        <td>1,008</td>
                        <td>Fusce</td>
                        <td>nec</td>
                        <td>tellus</td>
                        <td>sed</td>
                      </tr>
                      <tr>
                        <td>1,009</td>
                        <td>augue</td>
                        <td>semper</td>
                        <td>porta</td>
                        <td>Mauris</td>
                      </tr>
                      <tr>
                        <td>1,010</td>
                        <td>massa</td>
                        <td>Vestibulum</td>
                        <td>lacinia</td>
                        <td>arcu</td>
                      </tr>
                      <tr>
                        <td>1,011</td>
                        <td>eget</td>
                        <td>nulla</td>
                        <td>Class</td>
                        <td>aptent</td>
                      </tr>
                      <tr>
                        <td>1,012</td>
                        <td>taciti</td>
                        <td>sociosqu</td>
                        <td>ad</td>
                        <td>litora</td>
                      </tr>
                      <tr>
                        <td>1,013</td>
                        <td>torquent</td>
                        <td>per</td>
                        <td>conubia</td>
                        <td>nostra</td>
                      </tr>
                      <tr>
                        <td>1,014</td>
                        <td>per</td>
                        <td>inceptos</td>
                        <td>himenaeos</td>
                        <td>Curabitur</td>
                      </tr>
                      <tr>
                        <td>1,015</td>
                        <td>sodales</td>
                        <td>ligula</td>
                        <td>in</td>
                        <td>libero</td>
                      </tr>
                    </tbody>
                  </table>
                </div>
                  {% endblock %}
              </div>
            </div>
          </div>
          <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
          <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
          <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
        </body>
      </html>
    

students.html代码

	{% extends 'students/base.html' %}
	{% block title %}学生列表{% endblock %}
	{% block link %}{% endblock %}
	{% block section %}{{section}}{% endblock %}
	{% block content %}
	<div class="table-responsive">
	    <form action="" class="form-inline" style="margin-bottom:10px;">
	        <div class="form-group">
	            <input type="text" class="form-control" value="{{search}}" name="search" placeholder="姓名,qq,电话">
	        </div>
	        <button type="submit" class="btn btn-default">搜索</button>
	        <a href="{% url 'students:add' %}" class="btn btn-primary" role="button">添加</a>
	        <a href="{% url 'students:students' %}" class="btn btn-primary" role="button">重置</a>
	    </form>
	    <table class="table table-striped table-bordered">
	        <thead>
	        <tr>
	            <th>序号</th>
	            <th>姓名</th>
	            <th>年龄</th>
	            <th>性别</th>
	            <th>qq</th>
	            <th>电话</th>
	            <th>操作</th>
	        </tr>
	        </thead>
	        <tbody>
	        {% for stu in students %}
	        <tr>
	            <td>{{forloop.counter}}</td>
	            <td>{{stu.name}}</td>
	            <td>{{stu.age}}</td>
	            <td>{{stu.gender}}</td>
	            <td>{{stu.qq|default:'未填'}}</td>
	            <td>{{stu.phone|default:'未填'}}</td>
	            <td><a href="{% url 'students:edit' stu.id %}" class="btn btn-primary btn-xs" role="button">编辑</a>
	           <a href="{% url 'students:delete' %}?pk={{stu.id}}" class="btn btn-danger btn-xs" role="button">删除</a></td>
	        </tr>
	        {% endfor %}
	        </tbody>
	    </table>
	</div>
	{% endblock %}

student_edit代码

	<!--继承模板-->
	{% extends 'students/base.html' %}
	{% block title %}添加学生{% endblock %}
	{% block section %}{{section}}{% endblock %}
	{% block content %}
	<form class="form-horizontal" method="post">
	    {% csrf_token %}
	    <div class="form-group">
	        <!--lable标签中的for:当鼠标点到input标签的前面时,光标也进入input标签内,for的值和name的值一样,如果不一样,for不起作用-->
	        <label for="name" class="col-sm-2 control-label">姓名</label>
	        <div class="col-sm-3">
	            <input type="text" class="form-control" id="name" name="name" value="{{student.name}}">
	        </div>
	    </div>
	    <div class="form-group">
	        <label for="age" class="col-sm-2 control-label">年龄</label>
	        <div class="col-sm-2">
	            <input type="text" class="form-control" id="age" name="age" value="{{student.age}}">
	        </div>
	    </div>
	    <div class="form-group">
	        <label class="col-sm-2 control-label">性别</label>
	        <div class="col-sm-10">
	            <label class="radio-inline">
	                <input type="radio" name="gender" {% if student.gender == 1 %}checked{% endif %} id="inlineRadio1" value="1"> 男
	            </label>
	            <label class="radio-inline">
	                <input type="radio" name="gender" {% if student.gender == 0 %}checked{% endif %} id="inlineRadio2" value="0"> 女
	            </label>
	        </div>
	    </div>
	    <div class="form-group">
	        <label for="qq" class="col-sm-2 control-label">qq</label>
	        <div class="col-sm-3">
	            <input type="text" class="form-control" id="qq" name="qq" value="{{student.qq}}">
	        </div>
	    </div>
	    <div class="form-group">
	        <label for="phone" class="col-sm-2 control-label">电话</label>
	        <div class="col-sm-3">
	            <input type="text" class="form-control" id="phone" name="phone" value="{{student.phone}}">
	        </div>
	    </div>
	    <div class="form-group">
	        <label class="col-sm-2 control-label">年级</label>
	        <div class="col-sm-3">
	            <select class="form-control" name="grade">
	                <option  value="">未选班级</option>
	                {% for grade in grades %}
	                <option {% if student.grade_id == grade.id %}selected{% endif %} value="{{grade.id}}">{{grade.name}}</option>
	                {% endfor %}
	            </select>
	        </div>
	    </div>
	    <div class="form-group">
	        <label for="num" class="col-sm-2 control-label">身份证</label>
	        <div class="col-sm-3">
	            <input type="text" class="form-control" id="num" name="num" value="{{student.studentdetail.num}}">
	        </div>
	    </div>
	    <div class="form-group">
	        <label for="college" class="col-sm-2 control-label">毕业院校</label>
	        <div class="col-sm-3">
	            <input type="text" class="form-control" id="college" name="college" value="{{student.studentdetail.college}}">
	        </div>
	    </div>
	    <button type="submit" class="btn btn-primary">保存</button>
	</form>
	{% endblock %}

views.py代码

	from django.shortcuts import render,redirect,reverse
	from django.http import HttpResponse,JsonResponse
	from django.template.loader import get_template
	from datetime import datetime
	import os
	from django_test.settings import UPLOAD_ROOT
	from students.models import Student,Grade,StudentDetail
	from django.db.models import Q
	def students(request):		#主页面,students页面
	    section = '学生列表'
	    # 获取查询参数
	    search = request.GET.get('search','').strip()
	    if search:
	        if search.isdigit():
	            # 是qq或者电话号码
	            sts = Student.objects.filter(Q(qq=search)|Q(phone=search),is_deleted=False).order_by('-e_time')
	        else:   # 说明是姓名
	            sts = Student.objects.filter(name__contains=search,is_deleted=False).order_by('-e_time')
	    else:
	        sts = Student.objects.filter(is_deleted=False).order_by('-e_time')
	    return render(request,'students/students.html',context={'students':sts,'section':section,'search':search})
	def delete_student(request):		#删除方法
	    pk = request.GET.get('pk',None)
	    if pk:
	        student = Student.objects.get(pk=pk)
	        student.is_deleted = True
	        student.save()
	    return redirect(reverse('students:students'))
	def add_student(request):		#添加页面
	    section = '添加学生'
	    grades = Grade.objects.all()
	    if request.method == 'GET':
	        return render(request,'students/student_edit.html',context={
	            'section':section,
	            'grades':grades,
	        })
	    if request.method == 'POST':
	        data = {
	            'name':request.POST.get('name'),
	            'age':request.POST.get('age'),
	            'gender':request.POST.get('gender'),
	            'qq':request.POST.get('qq'),
	            'phone':request.POST.get('phone'),
	            'grade_id':request.POST.get('grade'),
	        }
	        student = Student(**data)
	        student.save()
	        student_detail = StudentDetail(
	            num = request.POST.get('num'),
	            college = request.POST.get('college'),
	            student=student
	        )
	        student_detail.save()
	        return redirect(reverse('students:students'))
	def edit_student(request,pk):		#编辑页面
	    student = Student.objects.get(pk=pk)
	    grades = Grade.objects.all()
	    if request.method == 'GET':
	        return render(request,'students/student_edit.html',context={
	            'student':student,
	            'grades':grades,
	        })
	    if request.method == 'POST':
	        student.name = request.POST.get('name')
	        student.age = request.POST.get('age')
	        student.qq = request.POST.get('qq')
	        student.gender = request.POST.get('gender')
	        student.phone = request.POST.get('phone')
	        student.grade_id = request.POST.get('grade')
	        student.save()
	        #判断一下,student有没有详情,如果没有,创建一个
	        try:
	            student_detail = student.studentdetail
	        except:
	            student_detail = StudentDetail()
	            student_detail.student = student
	        student_detail.num = request.POST.get('num')
	        student_detail.college = request.POST.get('college')
	        student.studentdetail.save()
	        return redirect(reverse('students:students'))

urls.py代码

	from django.urls import path, re_path
	from students import views
	app_name = 'students'
	urlpatterns = [
	    path('index/', views.index, name='index'),
	    path('detail/<int:pk>/',views.detail, name='aaa'),
	    path('login/',views.login,name='login'),
	    path('upload/',views.upload, name='upload'),
	    path('students_api/',views.students_api,name='students_api'),
	    path('students/',views.students,name='students'),
	    path('delete/',views.delete_student,name='delete'),
	    path('add/',views.add_student,name='add'),
	    path('edit/<int:pk>/',views.edit_student,name='edit'),
	]

base.css代码

  • 通过模板查到的渲染

      /*
       * Base structure
       */
      /* Move down content because we have a fixed navbar that is 50px tall */
      body {
        padding-top: 50px;
      }
      /*
       * Global add-ons
       */
      .sub-header {
        padding-bottom: 10px;
        border-bottom: 1px solid #eee;
      }
      /*
       * Top navigation
       * Hide default border to remove 1px line.
       */
      .navbar-fixed-top {
        border: 0;
      }
      /*
       * Sidebar
       */
      /* Hide for mobile, show later */
      .sidebar {
        display: none;
      }
      @media (min-width: 768px) {
        .sidebar {
          position: fixed;
          top: 51px;
          bottom: 0;
          left: 0;
          z-index: 1000;
          display: block;
          padding: 20px;
          overflow-x: hidden;
          overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
          background-color: #f5f5f5;
          border-right: 1px solid #eee;
        }
      }
      /* Sidebar navigation */
      .nav-sidebar {
        margin-right: -21px; /* 20px padding + 1px border */
        margin-bottom: 20px;
        margin-left: -20px;
      }
      .nav-sidebar > li > a {
        padding-right: 20px;
        padding-left: 20px;
      }
      .nav-sidebar > .active > a,
      .nav-sidebar > .active > a:hover,
      .nav-sidebar > .active > a:focus {
        color: #fff;
        background-color: #428bca;
      }
      /*
       * Main content
       */
      .main {
        padding: 20px;
      }
      @media (min-width: 768px) {
        .main {
          padding-right: 40px;
          padding-left: 40px;
        }
      }
      .main .page-header {
        margin-top: 0;
      }
      /*
       * Placeholder dashboard ideas
       */
      .placeholders {
        margin-bottom: 30px;
        text-align: center;
      }
      .placeholders h4 {
        margin-bottom: 0;
      }
      .placeholder {
        margin-bottom: 20px;
      }
      .placeholder img {
        display: inline-block;
        border-radius: 50%;
      }
    

效果图

  • 主界面
    在这里插入图片描述
  • 搜索界面
    在这里插入图片描述
    添加界面
    在这里插入图片描述
  • 修改界面
    在这里插入图片描述

异常

  • 运行时出现如下报错,找了好久没找到问题
    在这里插入图片描述
  • 后来在开发者知识库找到这个贴,再次查看
    在这里插入图片描述
  • 原来自己也犯这样的错误,college被错打成collage,改正后成功
    在这里插入图片描述

分页

手动分页

  • students.html部分代码:

      <div class="btn-group" role="group">
      <div class="btn-group" role="group">
      <nav aria-label="Page navigation">
          {% pagination_html %}
      </nav>
      </div>
      <div class="btn-group" role="group">
          <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ per_page }}条/页<span class="caret"></span></button>
          <ul class="dropdown-menu">
              <li><a href="{{ request.path }}?search={{ search }}&per_page=10">10条/页</a></li>
              <li><a href="{{ request.path }}?search={{ search }}&per_page=20">20条/页</a></li>
              <li><a href="{{ request.path }}?search={{ search }}&per_page=50">50条/页</a></li>
          </ul>
      </div>
      </div>
    
  • views.py的students的代码修改为:

      def students(request):
          section = '学生列表'
          # 获取查询参数
          search = request.GET.get('search','').strip()
          if search:
              if search.isdigit():
                  # 是qq或者电话号码
                  sts = Student.objects.filter(Q(qq=search)|Q(phone=search),is_deleted=False).order_by('-e_time')
              else:   # 说明是姓名
                  sts = Student.objects.filter(name__contains=search,is_deleted=False).order_by('-e_time')
          else:
              sts = Student.objects.filter(is_deleted=False).order_by('-e_time')
           #当前页码
          page = request.GET.get('page',1)
          page = int(page)
          #每页显示多少数据
          per_page = request.GET.get('per_page',10)
          per_page = int(per_page)
          total_num = sts.count()
          sts = sts[(page-1)*per_page:page*per_page]
          return render(request,'students/students.html',context={'students':sts,'section':section,'search':search,'per_page':per_page,'page':page,'total_num':total_num,})
    
  • pagination.html的代码:

      <ul class="pagination" style="margin:0px;">
          <li {% if page_num == 1 %}class="disabled"{% endif %}>
            <a href="{{request.path}}?search={{context.search}}&page={{page_num|add:'-1'}}&per_page={{context.per_page}}" aria-label="Previous">
              <span aria-hidden="true">上一页</span>
            </a>
          </li>
          {% for num in page_num_list %}
          <li {% if num == page_num %}class="active"{% endif %}><a href="{{request.path}}?search={{context.search}}&page={{num}}&per_page={{context.per_page}}">{{num}}</a></li>
          {% endfor %}
          <li {% if page_num == total_page %}class="disabled"{% endif %}>
            <a href="{{request.path}}?search={{context.search}}&page={{page_num|add:'1'}}&per_page={{context.per_page}}" aria-label="Next">
              <span aria-hidden="true">下一页</span>
            </a>
          </li>
      </ul>
    
  • customer_tags.py代码:

      @register.inclusion_tag('students/pagination.html',takes_context=True)
      def pagination_html(context):
          num =3  #总共显示多少页码
          page_num = context['page']
          per_page = context['per_page']
          students = context['students']
          total_num = context['total_num']    #总学生数
          total_page = math.ceil(total_num/per_page)  #总页数
          #页码列表
          page_list = []
          #生成当前页以及左边的页数
          if page_num - (num-1)//2 <= 0:  #左边页数从1开始
              for i in range(page_num):
                  page_list.append(i+1)
          else:   #左边的页数应该从page_num - (num-1)//2开始
              for i in range(page_num-(num-1)//2,page_num+1):
                  page_list.append(i)
          #生成当前页右边的页数
          if page_num + (num-1)//2 >= total_page:
              for i in range(page_num+1,total_page+1):
                  page_list.append(i)
          else:
              for i in range(page_num+1,page_num+(num-1)//2+1):
                  page_list.append(i)
          return {
              'page_num_list':page_list,
              'page_num':page_num,
              'context':context,
              'total_page':total_page,
          }
    

内置分页

  • 调试:

      In [1]: from students.models import Student                                                                                            
      In [2]: from django.core.paginator import Paginator                                                                                    
      In [5]: p = Paginator(Student.objects.all().order_by('-c_time'),3)                                                                     
      In [6]: p.count            #总共多少数据                                                                                                            
      Out[6]: 1
      In [7]: Student.objects.all().count()                #总共多少数据                                                                                  
      Out[7]: 1
      In [8]: p.num_pages                  #总页数                                                                                                  
      Out[8]: 1
      In [9]: p.page_range       #页码范围                                                                                                            
      Out[9]: range(1, 2)
      In [10]: page1 = p.page(1)         #第一页的数据     索引从1开始                                                                                               
      In [11]: page1.object_list                                                                                                             
      Out[11]: <QuerySet [<Student: wen-25>]>
      In [12]: page1.has_previous()  		#有没有上一页                                                                                                        
      Out[12]: False
      In [13]: page1.has_next()         #有没有下一页                                                                                                     
      Out[13]: False
      In [14]: page1.next_page_number()        #下一页的页码,因为目前只有第一页,所以下一页为空                                                                                              
      ---------------------------------------------------------------------------
      EmptyPage                                 Traceback (most recent call last)
      <ipython-input-14-cf6648317ae3> in <module>
      ----> 1 page1.next_page_number()
      ~/PycharmProjects/django/lib/python3.6/site-packages/django/core/paginator.py in next_page_number(self)
          162 
          163     def next_page_number(self):
      --> 164         return self.paginator.validate_number(self.number + 1)
          165 
          166     def previous_page_number(self):
      ~/PycharmProjects/django/lib/python3.6/site-packages/django/core/paginator.py in validate_number(self, number)
           47                 pass
           48             else:
      ---> 49                 raise EmptyPage(_('That page contains no results'))
           50         return number
           51 
      EmptyPage: That page contains no results
    

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值