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(
            '
  • ') else: page_li_list.append( '
  • '.format( page_num - 1 )) for i in range(page_start, page_end + 1): if i == page_num: page_li_list.append('
  • {}
  • '.format(i, i)) else: page_li_list.append('
  • {}
  • '.format(i, i)) if page_num == total_num: page_li_list.append( '
  • ') else: page_li_list.append( '
  • '.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(
                    '
  • ') # 页码不是1的都可以上翻页(bootstrap样式) else: page_li_list.append( '
  • '.format( self.page_num - 1)) # 将本次展示的页码
  • 标签全部加入字典中 for i in range(page_start, page_end + 1): # 如果该页码就是访问的页码加上一个(bootstrap样式) if i == self.page_num: page_li_list.append('
  • {}
  • '.format(i, i)) else: page_li_list.append('
  • {}
  • '.format(i, i)) # 下翻制作-点击页码为最后一个页码,则禁用(bootstrap样式) if self.page_num == self.total_num: page_li_list.append( '
  • ') # 页码不是最后页的都可以下翻页(bootstrap样式) else: page_li_list.append( '
  • '.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

    {{ obj.start_date|date:'Y-m-d' }}
    {{ obj.graduate_date|date:'Y-m-d' }}
    {{ obj.show_teachers }}

      补充班级相关增删改查逻辑 (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 %}
        
    class="container col-lg-4 col-md-offset-3" style="margin-top: 30px;">
    class="form-horizontal" method="post" novalidate> {% csrf_token %} {% for obj in form_obj %}
    class="form-group {% if obj.errors %}has-error{% endif %}">
    class="col-sm-10"> {{ obj }} class="help-block has-error">{{ obj.errors.0 }}
    {% endfor %}
    class="col-sm-offset-2 col-sm-10">
    {% endblock %} #####list.html {% extends 'layout.html' %} {% load static %} {% block js %} {% endblock %} {% block content %} class="text-center table table-striped table-bordered" style="margin-top: 20px"> {% for obj in msg %} {% endfor %}
    序号 id 部门 描述 操作
    {{ forloop.counter }} {{ obj.pk }} {{ obj.name }} {{ obj.desc }} 'crm:depedit' obj.pk %}>class="fa fa-pencil-square-o" aria-hidden="true">    class="b1" del_id="{{ obj.pk }}" style="color: red">class=" fa fa-remove" aria-hidden="true">
    {% endblock %}
    View Code

     

       

     

    你可能感兴趣的:(crm-2)