• django框架——sweetalert前端插件、序列化组件、批量数据操作、分页器、Forms组件(上)


    系列文章目录

    第一章 django安装与介绍

    第二章 django基础使用

    第三章 路由层

    第四章 虚拟环境、django版本区别、视图层

    第五章 模板层

    第六章 模型层(上)

    第七章 模型层(下)

    第八章 ajax

    第九章 sweetalert前端插件、序列化组件、批量数据操作、分页器、Forms组件(上)



    一、sweetalert前端插件

    下载地址


    二、序列化组件

    serializers是django自带的序列化数据的组件

    使用JsonResponse来转化数据发送到前端

    data_list = []  # [{}, {}, {}]  将json数据只作为列表套字典类型的
        user_queryset = models.User.objects.all()# 对于QuerySet格式的数据是无法序列化的
        for user_obj in user_queryset: 
            data_list.append({
                'uid':user_obj.uid,
                'username':user_obj.username,
                'password':user_obj.password,
            })
        return JsonResponse(data_list,safe=False)
        """ 使用jsonresponse可以高度定制我们需要的数据类型,缺点是数据多时使用麻烦
            [{
            "uid": 1,
            "username": "asdasd",
            "password": "123123"
            }, {
                "uid": 2,
                "username": "zxczxc",
                "password": "123123"
            },...
            ]
        """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    使用serializers来进行json序列化

    user_queryset = models.User.objects.all()
    ret = serializers.serialize('json', user_queryset) # 使用
    return HttpResponse(ret)
    """使用serializers可以快速生成json数据,格式也是固定的
    [{
    	"model": "app01.user", 数据所属的表
    	"pk": 1, 数据主键
    	"fields": { 具体的数据
    		"username": "asdasd",
    		"password": "123123"
    	}
    }, {
    	"model": "app01.user",
    	"pk": 2,
    	"fields": {
    		"username": "zxczxc",
    		"password": "123123"
    	}
    }, ...
    ]
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    三、批量数据操作

    django插入数据到数据库是很慢的,当我们一口气需要插入很多数据时需要优化数据的插入。

    django插入数据通过models中的类进行的,所以我们先将数据转化为对应的类,可以大大节省django插入数据库时的转化对应表对象的过程,从而大大节省插入数据时间

    def add_data(request):
        user_list = []
        for i in range(100000):
            # 先用类产生一个对象
            source_book_obj = models.User(username=f'username{i}',password=f'password{i}')
            # 将对象追加到列表中
            user_list.append(source_book_obj)
        models.User.objects.bulk_create(user_list)  # 批量插入
        user_queryset = models.User.objects.all()
        return render(request, 'add_data.html', locals())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    四、分页器

    前端不可能将所有的数据全部展示到一页,应该考虑使用分页,每页展示一些,前端很多地方都需要分页所以有了分页的模块。

    此处提供的自定义分页器模块需要搭配bootstrap来使用,也可以自行修改分页器和内容显示区域的样式

    首先创建一个utils包

    创建一个py文件在其中添加以下代码

    class Pagination(object):
        def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
            """
            封装分页相关数据
            :param current_page: 当前页
            :param all_count:    数据库中的数据总条数
            :param per_page_num: 每页显示的数据条数
            :param pager_count:  最多显示的页码个数
            """
            try:
                current_page = int(current_page)
            except Exception as e:
                current_page = 1
    
            if current_page < 1:
                current_page = 1
    
            self.current_page = current_page
    
            self.all_count = all_count
            self.per_page_num = per_page_num
    
            # 总页码
            all_pager, tmp = divmod(all_count, per_page_num)
            if tmp:
                all_pager += 1
            self.all_pager = all_pager
    
            self.pager_count = pager_count
            self.pager_count_half = int((pager_count - 1) / 2)
    
        @property
        def start(self):
            return (self.current_page - 1) * self.per_page_num
    
        @property
        def end(self):
            return self.current_page * self.per_page_num
    
        def page_html(self):
            # 如果总页码 < 11个:
            if self.all_pager <= self.pager_count:
                pager_start = 1
                pager_end = self.all_pager + 1
            # 总页码  > 11
            else:
                # 当前页如果<=页面上最多显示11/2个页码
                if self.current_page <= self.pager_count_half:
                    pager_start = 1
                    pager_end = self.pager_count + 1
    
                # 当前页大于5
                else:
                    # 页码翻到最后
                    if (self.current_page + self.pager_count_half) > self.all_pager:
                        pager_end = self.all_pager + 1
                        pager_start = self.all_pager - self.pager_count + 1
                    else:
                        pager_start = self.current_page - self.pager_count_half
                        pager_end = self.current_page + self.pager_count_half + 1
    
            page_html_list = []
            # 添加前面的nav和ul标签
            page_html_list.append('''
                        <nav aria-label='Page navigation>'
                        <ul class='pagination'>
                    ''')
            first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
            page_html_list.append(first_page)
    
            if self.current_page <= 1:
                prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
            else:
                prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
    
            page_html_list.append(prev_page)
    
            for i in range(pager_start, pager_end):
                if i == self.current_page:
                    temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
                else:
                    temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
                page_html_list.append(temp)
    
            if self.current_page >= self.all_pager:
                next_page = '<li class="disabled"><a href="#">下一页</a></li>'
            else:
                next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
            page_html_list.append(next_page)
    
            last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
            page_html_list.append(last_page)
            # 尾部添加标签
            page_html_list.append('''
                                               </nav>
                                               </ul>
                                           ''')
            return ''.join(page_html_list)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    视图函数:

    from utils import mypage # 导入刚才创建的py文件
    user_queryset = models.User.objects.all()
    # 1.产生分页器对象
    '''针对于Pagination有以下几个关键字参数
    current_page: 当前页
    all_count:    数据库中的数据总条数
    per_page_num: 每页显示的数据条数
    pager_count:  最多显示的页码个数
    '''
    page_obj = mypage.Pagination(current_page=request.GET.get('page'),all_count=user_queryset.count())
    
    # 2.产生分页数据对象
    page_queryset = user_queryset[page_obj.start:page_obj.end]
    return render(request,'many_data.html',locals())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    显示层:

    注意导入bootstrap

    
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                {% for user in page_queryset %}
                <p>{{ user.username }}</p>
                <p>{{ user.password }}</p>
                {% endfor %}
                {{ page_obj.page_html|safe }}
            </div>
        </div>
    </div>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    五、Forms组件(上)

    django提供的forms组件可以实现快速产生获取数据的标签、数据验证、错误信息的反馈

    使用前提

    编写自己的Forms

    参数作用
    min_length字符串最小长度
    max_length字符串最大长度
    min_value数字最小位数
    max_value数字最大位数
    label对应的label值
    required验证时可以为空
    from django import forms
    class MyForm(forms.Form):
        # 用户名至少三个字符最多八个字符
        username = forms.CharField(min_length=3,max_length=8, label="用户名")
        # 密码最小不能小于4 最大不能超过16
        password = forms.CharField(min_length=6,max_length=16, label="密码")
        # 邮箱必须符合邮箱格式(@关键符号)
        email = forms.EmailField(required=True, label="邮箱")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1.校验数据

    	data = request.POST
    	# 1.将数据传入实例化对象
        form_obj = MyForm({"username":data.get('username'), "password":data.get('password'), "email":data.get('email')}) # 放入对应的字典数据 可以使用 **data 直接传入
        # 2.查看数据是否合法(全部合法结果才是True)
        form_obj.is_valid()
        # 3.查看不符合条件的数据及原因
        form_obj.errors # 类似这种 {'email': ['Enter a valid email address.']}
        # 4.查看符合条件的数据
        form_obj.cleaned_data # 符合条件的数据 {'username': 'kdq', 'password': k12345}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.渲染标签

    forms组件只负责渲染获取用户数据的标签
    form表单标签和提交按钮需要自己写

    2.1渲染方式1

    封装程度高 扩展性较差 主要用于快速生成页面测试功能

    {{ form_obj.as_p }} {# 这种注释中label和input会渲染在p标签中 #}
    
    • 1

    通过下图可以看出label和input在p中
    错误信息在ul li中
    在这里插入图片描述

     {{ form_obj.as_table }} <!-- 这种注释中lable和input直接渲染 -->
    
    • 1

    通过下图可可以看出label和input直接渲染
    错误信息在ul li中

    在这里插入图片描述

      {{ form_obj.as_ul }} {# label和input渲染在li中 #}
    
    • 1

    通过下图可可以看出label和input渲染在li中
    错误信息在li下的ul li中
    在这里插入图片描述

    2.2渲染方式2

    封装程度低 扩展性较好 但是字段比较多的情况下不方便

    此时form_obj.username.label获取的只是对应input的label文本需要自行定制样式
    form_obj.username将会渲染出input

    <form action="" method="post">
            <div class="form-group">
                <label for="">{{ form_obj.username.label }}</label>
                {{ form_obj.username }}
            </div>
            <div class="form-group">
                <label for="">{{ form_obj.password.label }}</label>
                {{ form_obj.password }}
            </div>
            <div class="form-group">
                <label for="">{{ form_obj.email.label }}</label>
                {{ form_obj.email }}
            </div>
            <button type="submit" id="logobtn" class="btn btn-default">登录</button>
        </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    2.3 渲染方式3

    高度定制化,同时可以使用模板语法快速渲染

    <form action="" method="post">
            {% for form in form_obj %}
                <div class="form-group">
                    <label>{{ form.label }}</label>
                    {{ form }}
                </div>
            {% endfor %}
    
            <button type="submit" id="logobtn" class="btn btn-default">登录</button>
        </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    3.展示信息

    forms类中填写的校验性参数前端浏览器会识别并添加校验操作,前端的验证操作是可以被轻易修改的,最好是在后端验证
    form表单可以取消浏览器自动添加校验功能的操作

    <form action="" method="post" novalidate></form> {# 只要添加novalidate就能不触发forms组件的验证 #}
    
    • 1

    错误信息的前端获取方式

    {{ form.errors.0 }} 
    
    • 1

    提示信息可以自定义

    在对应字段中设置error_messages即可

    from django import forms
    class MyForm(forms.Form):
        # 用户名至少三个字符最多八个字符
        username = forms.CharField(min_length=3,max_length=8, label="用户名", error_messages={
                             'min_length':'用户名最短3位',
                              'max_length':'用户名最长8位',
                              'required':'用户名必填'
                                   })
        # 密码最小不能小于4 最大不能超过16
        password = forms.CharField(min_length=6,max_length=16, label="密码")
        # 邮箱必须符合邮箱格式(@关键符号)
        email = forms.EmailField(required=True, label="邮箱")
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    腾讯mini项目-【指标监控服务重构】2023-07-17
    1、Kafka 安装与简单使用
    typeof null 为什么是object
    浏览器不能访问阿里云ECS
    基于移动GIS的环保生态管理系统
    Java以form-data(表单)的形式调用第三方接口
    报表工具,应该适用哪种部署方式?_光点科技
    举个栗子~Alteryx 技巧(3):离线激活 Alteryx Designer
    入门深度学习—从配置python到网络模型
    PAT A1014 Waiting in Line
  • 原文地址:https://blog.csdn.net/kdq18486588014/article/details/124888911