zoukankan      html  css  js  c++  java
  • crm-2

    1.分页

      web必备的功能

      1)批量制造测试数据

        定义一个空列表用于存储 orm对象 ,models.表名(字段=...)创建orm对象append到列表 ,使用bulk_create(对象列表)一次性提交 ,避免了多次与数据库连接损耗

    #脚本加载django环境
    import os
    
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "untitled.settings")
        import django
    
        django.setup()
        from crm import models
        from django.db import transaction
        DepObjList = []
        for i in range(1,300):
            obj = models.Dep(name='部门{}'.format(i))
            print(obj)
            DepObjList.append(obj)
        models.Dep.objects.bulk_create(DepObjList)

      2)分页明确所需要的数据

        后端分页的减轻数据库压力

        per_num =  每页最大显示的页码数(自定义一个值如 20 50)

        all_count = 一共有多少条数据需要展示(所有数据对象列表.count())

        max_show = 底部页码栏展示的长度 (这里有左极值和右极值 ,以及访问页码时保证当前页码在中间显示)

        half_show = 底部页码栏展示的一半是多少max_show // 2

        page_num = 当前访问的页码 (根据该页码展示数据)

        total_num = 页码的总数

        start      #根据当前访问的页码计算开始切片的索引

        end       #根据当前访问的页码计算结束切片的索引

        page_html    #生成底部页码的标签返回html页面

      3)放在list视图函数中 ,因为前端的逻辑不太好写 ,所以将逻辑放在后端写 ,生成的标签通过mark_safe()转换为浏览器可解析的无需前端加safe    

         实现的点

          (1)页码长度为固定值max_show ,且该值位于中心 ,左右有half_show的长度页码 (3 4 5 6 7 8 9 10 11 12 13 )  选中8那么3-7和9-13就是half_show的长度!!

            (2)   页码总数total_num小于max_show的情况下

          (3)页码左极值不允许出现负值 ,如果按照中心定值那么一定会出现 (-2 -1 0 1 2 3 4 5 6 7 8  )选中3那么出现了负数页码 !! 改进当选中小于half_show的长度固定 1-max_show的页码

          (4)页码右极值不允许出现超过total_num的值 ,如果按照中心定值会出现超出total_num的页码数 ! !改进当选中大于total_num-half_show ,长度固定 total_num减max_show - total_num页码

            (5)   页码无极值问题情况下

            (6)   每页根据当前页码 ,将对象列表切片显示本页码的数据

            (7)   由于前段逻辑判断不好写, 放在后端写页码的li标签,其中当页码等于1或最后一页的时候需要禁止两侧按钮 ,放入列表拼接字符串转为安全代码传给前端展示

    def deplist(request):
        all_obj = models.Dep.objects.all()
        per_num = 10
        all_count = all_obj.count()
        max_show = 11
        half_show = max_show // 2
    
        # 当前访问的页面默认是1 ,如果url上有访问的page那么使用request.GET的参数
        page_num = 1
        if request.GET.get('page'):
            page_num = int(request.GET.get('page'))
    
        total_num = all_count // per_num
        # 最后一页的数据可能不够per_num那也需要展示 所以总页码数再加1
        if all_count % per_num != 0:
            total_num += 1    """
        限制底部页码长度 ,保证左右极值不会小于1 大于total_num ,并且保证长度
            如点击标签8 ,那么保证8在中间 ,前后分别增加5个标签 ,《3 4 5 6 7 8 9 10 11 12 13》
        """# 当页码不足定义好的最长的时候 ,有多长显示多长
        if total_num < max_show:
            page_start = 1
            page_end = total_num
        # 当页码足够多的时候 ,考虑左右极值的情况处理
        else:
            # 左极值!如果访问页码小于 页码预设半长 ,那么直接显示1-max_show
            if page_num <= half_show:
                page_start = 1
                page_end = max_show
            # 右极值!访问如果超过了total_num - half_show那么显示total_num-max_show到total_num这个固定长度
            elif page_num > total_num - half_show:
                page_start = total_num - max_show+1
                page_end = total_num
            # 无极值情况下
            else:
                page_start = page_num - half_show
                page_end = page_num + half_show
    
        """
        切片(规律)的到start与end索引值
            1页展示数据            msg:[0:30]
            2页展示数据            msg:[30:60]
            ...
            page_num展示数据       msg:[(page_num - 1) * per_num : page_num * per_num]
        """
        start = (page_num - 1) * per_num
        end = page_num * per_num
    
        page_li_list = []
        if page_num == 1:
            page_li_list.append(
                '<li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>')
    
        else:
            page_li_list.append(
                '<li ><a href="?page={}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>'.format(
                    page_num - 1
                ))
    
        for i in range(page_start, page_end + 1):
            if i == page_num:
                page_li_list.append('<li class="active"><a href="?page={}">{}</a></li>'.format(i, i))
            else:
                page_li_list.append('<li><a href="?page={}">{}</a></li>'.format(i, i))
    
        if page_num == total_num:
            page_li_list.append(
                '<li class="disabled"><a href="#" aria-label="Next"><span aria-hidden="true">&raquo;</span></a>')
        else:
            page_li_list.append(
                '<li ><a href="?page={}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a>'.format(page_num + 1)
            )
    
        page_html = ''.join(page_li_list)
    
        return render(request, 'deplist.html',
                      {'msg': all_obj[start:end], 'page_html': mark_safe(page_html)})

    2.分页使用类实现复用

      定义一个类

    ####定义文件Pageination.py
    
    """
    使用方法:
        在逻辑中引用实例化对象,一般来说page_num = request.GET.get('page',1)  all_count=models...all().count()
        在返回值中调用start与end方法获取到切片的索引!
    
    
    
    """
    class Pageination:
    
        def __init__(self, page_num, all_count, per_num=20, max_show=11, ):
    
            # 当前访问页码值
            try:
                self.page_num = int(page_num)
            except Exception as e:
                self.page_num = 1
    
            # 数据总条数
            self.all_count = all_count
    
            # 每页最大显示数据条数
            self.per_num = per_num
    
            # 每页底部页码长度
            self.max_show = max_show
            self.half_show = self.max_show // 2
    
            # 计算页码总量 ,divmod方法 ,返回两个参数的 整除数 ,取余数,分别用两个参数接收
            self.total_num, more = divmod(self.all_count, self.per_num)
            # total_num就是总共的页码数
            if more != 0:
                self.total_num += 1
    
        # 根据页码生成给数据切片的索引
        @property  # 方法调用变属性
        def start(self):
            return (self.page_num - 1) * self.per_num
    
        @property  # 方法调用变属性
        def end(self):
            return self.page_num * self.per_num
    
        # 根据页码页码底部html标签
        @property  # 方法调用变属性
        def page_html(self):
            # 限制起始值与终止值 ,当页码不足max_show ,那就直接将最大页码去显示
            if self.total_num < self.max_show:
                page_start = 1
                page_end = self.total_num
            else:
                # 左极值:防止负页码 ,当页码数小于5 就不要放把5中间了直接1-最大显示了
                if self.page_num <= self.half_show:
                    page_start = 1
                    page_end = self.max_show
    
                # 右极值:防止显示页码数大于页码总数 ,当某个页码数 ,该页码数的后面加上half_show超过了总页码数
                elif self.page_num + self.half_show > self.total_num:
                    # 我们将页码开始显示为总页码数减去每次显示的最大数 +1 获得了最后允许显示的开始值
                    page_start = self.total_num - self.max_show + 1
                    # 将最大页码数作为结束值
                    page_end = self.total_num
                else:
                    page_start = self.page_num - self.half_show
                    page_end = self.page_num + self.half_show
    
            # 将前端标签一个个追加到列表中(上翻-所有页码-下翻),加完之后统一生成一个str传到前端展示
            page_li_list = []
    
            # 上翻制作-本页码为1,则禁用(bootstrap样式)
            if self.page_num == 1:
                page_li_list.append(
                    '<li class="disabled"><a href="" aria-label="Next"><span aria-hidden="true">&laquo;</span></a></li>')
            # 页码不是1的都可以上翻页(bootstrap样式)
            else:
                page_li_list.append(
                    '<li><a href="?page={}" aria-label="Next"><span aria-hidden="true">&laquo;</span></a></li>'.format(
                        self.page_num - 1))
    
            # 将本次展示的页码<li>标签全部加入字典中
            for i in range(page_start, page_end + 1):
                # 如果该页码就是访问的页码加上一个(bootstrap样式)
                if i == self.page_num:
                    page_li_list.append('<li class="active"><a href="?page={}">{}</a></li>'.format(i, i))
                else:
                    page_li_list.append('<li><a href="?page={}">{}</a></li>'.format(i, i))
    
            # 下翻制作-点击页码为最后一个页码,则禁用(bootstrap样式)
            if self.page_num == self.total_num:
                page_li_list.append(
                    '<li class="disabled"><a href="" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>')
            # 页码不是最后页的都可以下翻页(bootstrap样式)
            else:
                page_li_list.append(
                    '<li><a href="?page={}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>'.format(
                        self.page_num + 1))
    
            # 将列表内容拼接成一个字符串,也就是很多的li标签HTML代码 ,直接返回给前端
            return ''.join(page_li_list)
    View Code

      实例化引用

    def deplist(request):
        all_obj = models.Dep.objects.all()
        pageobj = Pageination(request.GET.get('page', 1), all_obj.count())
        return render(request, 'deplist.html',
                      {'msg': all_obj[pageobj.start:pageobj.end], 'page_html': mark_safe(pageobj.page_html)})

    3.crm数据补充

      部门表,人员表的逻辑完成 , 新增班级表+课程表+校区表 ,其中班级表中外键课程和校区 ,多对多到人员表

      问题1:多对多的表中 ,拥有mantomany字段的表会出现显示关系管理对象问题  解决1:在model中定义一个方法返回关系管理对象中所有对象名字 ,前端执行这个方法显示

      问题2:前端显示时间的问题使用date: 'Y-m-d'解决

    ##models
    class
    ClassList(models.Model): """班级表 其中任课老师与班级是多对多的""" ...... def __str__(self): return str(self.semester) def show_teachers(self): return ','.join([i.name for i in self.teachers.all()])


    ##html

    <td>{{ obj.start_date|date:'Y-m-d' }}</td>
    <td>{{ obj.graduate_date|date:'Y-m-d' }}</td>
    <td>{{ obj.show_teachers }}</td>

      补充班级相关增删改查逻辑 (edit与add整合为change)

    #####url
        url(r'^class/list/', classes.classes_list, name='classes_list'),
        url(r'^class/add/', classes.classes_change, name='classes_add'),
        url(r'^class/edit/(d+)', classes.classes_change, name='classes_edit'),
        url(r'^class/del/(d+)', classes.classes_del, name='classes_del'),
    
    #####models
    class Course(models.Model):
        """课程名"""
        name = models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
    
    
    class School(models.Model):
        """校区名"""
        name = models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
    
    
    class ClassList(models.Model):
        """班级表   其中任课老师与班级是多对多的"""
        school = models.ForeignKey('School', verbose_name='校区名')
        course = models.ForeignKey('Course', verbose_name='课程表')
        semester = models.IntegerField(verbose_name='班级')
        price = models.IntegerField(verbose_name='价格')
        start_date = models.DateField(verbose_name='开班日期')
        graduate_date = models.DateField(verbose_name='结业日期', null=True, blank=True)
        tutor = models.ForeignKey(verbose_name='班主任', to='User', related_name='classes')
        teachers = models.ManyToManyField(verbose_name='任课老师', to='User', related_name='teach_classes')
        memo = models.CharField(verbose_name='说明', max_length=255, blank=True, null=True)
    
        def __str__(self):
            return str(self.semester)
    
        def show_teachers(self):
            return ','.join([i.name for i in self.teachers.all()])
    
    
    #####modelform
    
    class ClassFrom(forms.ModelForm):
        class Meta:
            model = models.ClassList
            fields = '__all__'
    
        def __init__(self, *args, **kwargs):
            super(ClassFrom, self).__init__(*args, **kwargs)
            for field in self.fields.values():
                print(field)
                field.widget.attrs.update({'class': 'form-control'})
    
    
    #####view
    
    from django.shortcuts import render, reverse, redirect, HttpResponse
    from crm import models
    from crm.modleforms import ClassFrom
    
    
    def classes_list(request):
        all_class = models.ClassList.objects.all()
        return render(request, 'classes_list.html', {'msg': all_class})
    
    
    def classes_change(request, edit_id=None):
        obj = models.ClassList.objects.filter(pk=edit_id).first()
        form_obj = ClassFrom(instance=obj)
        if request.method == 'POST':
            form_obj = ClassFrom(request.POST, instance=obj)
            if form_obj.is_valid():
                form_obj.save()
                return redirect(reverse('crm:classes_list'))
        return render(request, 'depadd-edit.html', {'form_obj': form_obj})
    
    def classes_del(request, del_id):
        obj = models.ClassList.objects.filter(pk=del_id).delete()
        return redirect(reverse('crm:classes_list'))
    
    #####edit.hrml
    {% extends 'layout.html' %}
    {% block content %}
        <div class="container col-lg-4 col-md-offset-3" style="margin-top: 30px;">
            <form class="form-horizontal" method="post" novalidate>
                {% csrf_token %}
                {% for obj in form_obj %}
                    <div class="form-group  {% if obj.errors %}has-error{% endif %}">
                        <label for="{{ obj.id_for_label }}"
                               class="col-sm-2 control-label">{{ obj.label }}</label>
                        <div class="col-sm-10">
                            {{ obj }}
                            <span class="help-block has-error">{{ obj.errors.0 }}</span>
                        </div>
                    </div>
                {% endfor %}
                <div class="col-sm-offset-2 col-sm-10">
                    <button type="submit" class="btn btn-default">保存</button>
                </div>
            </form>
        </div>
    {% endblock %}
    
    
    #####list.html
    {% extends 'layout.html' %}
    {% load static %}
    {% block js %}
        <script src="{% static '/js/sweetalter.js' %}"></script>
        <script>
    
            $('.b1').click(function () {
    
                swal({
                    title: "提示",
                    text: "删除后无法恢复",
                    icon: "warning",
                    buttons: true,
                    dangerMode: true,
                })
                    .then((willDelete) => {
                        let del_id = $(this).attr('del_id');
                        if (willDelete) {
                            $.ajax({
                                url: '/crm/dep/del/' + del_id,
                                type: 'get',
                                success: () => {
                                    swal("已删除!", {
                                        icon: 'success',
                                    });
                                    $(this).parent().parent().remove()
                                }
                            });
                        } else {
                            swal("取消删除!");
                        }
                    });
            })
        </script>
    {% endblock %}
    {% block content %}
        <table class="text-center table table-striped table-bordered" style="margin-top: 20px">
            <tr>
                <td>序号</td>
                <td>id</td>
                <td>部门</td>
                <td>描述</td>
                <td>操作</td>
            </tr>
            {% for obj in msg %}
                <tr>
                    <td>{{ forloop.counter }}</td>
                    <td>{{ obj.pk }}</td>
                    <td>{{ obj.name }}</td>
                    <td>{{ obj.desc }}</td>
                    <td><a href={% url 'crm:depedit' obj.pk %}><i class="fa fa-pencil-square-o" aria-hidden="true">&nbsp&nbsp&nbsp</i></a>
                        <a class="b1" del_id="{{ obj.pk }}" style="color: red"><i class=" fa fa-remove"
                                                                                  aria-hidden="true"></i></a></td>
                </tr>
            {% endfor %}
        </table>
    
        <nav aria-label="Page navigation">
            <ul class="pagination">
                {{ page_html }}
            </ul>
        </nav>
    
    
    
    {% endblock %}
    View Code

       

  • 相关阅读:
    android 布局中的单位及分辨率自解
    7种例子讲解Android Dialog!
    jqDnR 层拖动插件 潇湘博客
    jQuery选择器热榜
    左边补0 php 潇湘博客
    Javascript代码压缩、加密算法的破解分析及工具实现
    discuz 整合总结
    js 格式化 潇湘博客
    Linux内核网络协议栈深入分析(五)套接字的绑定、监听、连接和断开
    Linux内核基于Netfilter的内核级包过滤防火墙实现
  • 原文地址:https://www.cnblogs.com/quguanwen/p/11445880.html
Copyright © 2011-2022 走看看