今日内容 批量操作数据,分页器使用 form与modelform组件
- 
批量操作数据
使用create创建大量数据:
# 涉及到大批量数据的创建 直接使用create效率非常低并且可能会造成数据库崩溃 
def index(request):
    for i in range(100000):
        models.Book.objects.create(title=f'第{i}本书')   # 创建100000条数据
    book_query = models.Book.objects.all()    # 查询所有数据
    return  render(request, 'bookList.html', locals())  # 把数据展示到html页面中
使用bulk_create进行批量创建
def index(request):
    book_list = []  # 空列表
    for i in range(100000):
        book_obj = models.Book(title=f'第{i}本书') # 创建书籍对象
        book_list.append(book_obj)  # 数据添加到列表
    # 上述四行可以用列表生成式简写为一行
    # [models.Book(title=f'第{i}本书') for i in range(100000)]
    models.Book.objects.bulk_create(book_list)   # bulk_create批量创建
    book_query = models.Book.objects.all()    # 查询所有数据
    return  render(request, 'bookList.html', locals())  # 把数据展示到html页面中
- 
批量数据展示
分页器推导流程
当数据量比较大的时候 页面展示应该考虑分页
1.QuerySet切片操作
2.分页样式添加
3.页码展示
   如何根据总数据和每页展示的数据得出总页码
   divmod()
4.如何渲染出所有的页码标签
   前端模板语法不支持range 但是后端支持 我们可以在后端创建好html标签然后传递给html页面使用
5.如何限制住展示的页面标签个数
   页码推荐使用奇数位(对称美)  利用当前页前后固定位数来限制
6.首尾页码展示范围问题
 
- 
自定义分页器
上面是自定义分页器开发流程的基本思路,我们不需要掌握代码的编写,只需要掌握基本用法即可
自定义分页器封装代码:
点击查看代码
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)
后端的使用
from app01.plugins import mypage  #  mypage里放封装后的分页器代码
book_query = models.Book.objects.all()
page_obj = mypage.Pagination(current_page=request.GET.get('page'),
                             all_count=book_query.count()
                            )
page_query = book_query[page_obj.start:page_obj.end]
return render(request, 'bookList.html', locals())
前端的使用
{% for book_obj in page_query %}
	<p class="text-center">{{ book_obj.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}
- 
form组件
一.form组件的功能
   1.数据校验功能
   2.渲染标签功能
   3.展示提示信息功能
准备工作
def ab_form(request):
    data_dict = {'username':'','password':''}
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'jason':
            data_dict['username'] = 'jason是你能随便用的吗'
        if password == '123':
            data_dict['password'] = '密码就设123???'
    return render(request,'ab_form.html',locals())
1.form类型创建
from django import forms
    class MyForm(forms.Form):
        name = forms.CharField(max_length=8, min_length=3)  # 用户名最长八个字符 最短三个字符
        age = forms.IntegerField(max_value=150, min_value=0)  # 年龄最小0岁 最大150岁
        email = forms.EmailField()  # 邮箱必须符合邮箱格式(至少有个@符号)
2.数据校验功能
1.1.传递待校验的数据
    	form_obj = views.MyForm({'name':'jason','age':18,'email':123})
1.2.判断所有的数据是否符合校验
    	form_obj.is_valid()
1.3.获取符合校验规则的数据
    	form_obj.cleaned_data
    	{'name': 'jason', 'age': 18}
1.4.查阅不符合校验规则的数据及错误原因
    	form_obj.errors
    	{'email': ['Enter a valid email address.']}
 	"""
 	1.form类中编写的字段默认都是必填的 少传则肯定通不过校验 is_valid
 	2.校验如果多传了一些字段 则不参与校验 全程忽略
 	"""
3.渲染标签功能
2.1.方式1(封装程度高 扩展性差)
    	{{ form_obj.as_p }}
 		{{ form_obj.as_table }}
       {{ form_obj.as_ul }}
2.2.方式2(封装程度低 扩展性好 编写困难)
    	{{ form_obj.name.lable }}
      	{{ form_obj.name }}
2.3.方式3(推荐使用)
    	{% for form in form_obj %}
        <p>{{ form.label }}{{ form }}</p>
    	{% endfor %}
 	"""
 	类中以外的所有标签都不会自动渲染 需要自己编写
 	"""
4.展示提示信息功能
form表单如何取消浏览器自动添加的数据校验功能
    	<form action="" method="post" novalidate>
   	{% for form in form_obj %}
        <p>
            {{ form.label }}{{ form }}
            <span style="color: red;">{{ form.errors.0 }}</span>
        </p>
    {% endfor %}
    <input type="submit" value="提交">
   	
    def func(request):
        form_obj = MyForm()
        if request.method == 'POST':
            form_obj = MyForm(request.POST)
            if form_obj.is_valid():
                print(form_obj.cleaned_data)
        return render(request,'func.html',locals())
三.重要的字段参数
     max_length                   最大长度
     min_length                   最小长度
     max_value                    最大值
     min_value                    最小值
     label			  字段注释
     error_messages		  错误提示
     required			  是否为空
     widget		          标签类型、标签属性
     initial			  默认值
     validators			  正则校验
四.钩子函数
提供自定义的校验方式
 	局部钩子:校验单个字段
        def clean_name(self):
            name = self.cleaned_data.get('name')
            res = models.User.objects.filter(name=name).first()
            if res:
                return self.add_error('name','用户名已存在')
            return name
 	全局钩子:校验多个字段
        def clean(self):
            pwd = self.cleaned_data.get('pwd')
            confirm_pwd = self.cleaned_data.get('confirm_pwd')
            if not pwd == confirm_pwd:
                return self.add_error('confirm_pwd','两次密码不一致')
            return self.cleaned_data
- 
modelform组件
modelform是form的优化版本 使用更简单 功能更强大
class MyModelForm(forms.ModelForm):
    class Meta:
        model = models.User
        fields = '__all__'
    def clean_name(self):
        name = self.cleaned_data.get('name')
        res = models.User.objects.filter(name=name).first()
        if res:
            self.add_error('name','用户名已存在')
        return name

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号