139 分页器和django中的form校验

昨日回顾

1 ajax:异步的javascript的xml,同时可以发出很多ajax的请求,局部刷新
2 本质就是使用javascript这门语言发送http请求,(异步),原生,jquery的ajax方法,axios
3 如何使用(借助于jquery)
	# 默认编码方式是urlencoded
	$.ajax({
        url:/books/?name=lqz,
        method:'post/get',
        data:{name:'lqz',age:19},
        success:function (data){
            打印,弹窗,渲染页面(js dom操作,修改页面)
        }
    })
4 上传文件
	var formdata=new Formdata()
    formdata.append('name','lqz')
    formdata.append('myfile',$('#id_file')[0].files[0])
	$.ajax({
        url:/books/?name=lqz,
        method:'post/get',
        processData:false,
        contentType:false,
        data:formdata,
        success:function (data){
            打印,弹窗,渲染页面(js dom操作,修改页面)
        }
    })
    # 后端代码写一套即可:使用form表单传,postman,ajax传,都是一样的
    
    
5 上传json格式
	$.ajax({
        url:/books/?name=lqz,
        method:'post/get',
        contentType:'application/json',
        data:字符串(json格式),
        success:function (data){
            打印,弹窗,渲染页面(js dom操作,修改页面)
        }
    })
    
6 后端返回数据
	-HttpResponse:它没有指定,text/html
    -JsonResponse:它指定了响应编码:application/json
    -ajax方法:会去看响应编码是什么,如果是application/json,自动调用JSON.parser(),如果不是json格式,就不处理
    -于是:success:function (data)  可能是个字符串,也可能是个对象,响应编码决定的
    
    
7 js中json序列化和反序列化
	-JSON.parser()
    -JSON.stringify(data)
    
    
8 django内置的序列化器
	-需要会自己转(把对象转成json格式)
    -自己写(局限性,以后再转publish,还得再写一遍,不通用)
        ll=[]
        for book in book_list:
            ll.append({'name':book.name,'age':book.age})
        return JsonResponse(ll,safe=False)
    
    {name:lqz,age:18,hobbys:[{hobbyname:'篮球',hobbyid:1},{hobbyname:'足球',hobbyid:2}]}
    
    [{name:lqz,age:18},{name:egon,age:18},{name:zs,age:18}]

今日内容

# 批量插入数据
l=[]
for i in range(100):
  book = models.Book(name=f'书{i}', price=i)
  l.append(book)
  models.Book.objects.bulk_create(l,10)
  
#### 数据库查询的顺序 ####
	class Meta:
		ordering = ('id',)  # 默认id排序

1 分页器组件介绍

1 项目数据量大了以后,涉及到分页,一页一页的加载显示
2 django中分页器组件,把分页常用的东西,封装到一个类中
3 实例化一个对象,对象里有属性和方法
# 分页器对象和页对象的一些用法
from django.core.paginator import Paginator

def func139_1(request):
	book_list = models.Book.objects.all()

	# 实例化得到对象
	# 第一个参数:要分页的数据,book_list
	# 第二个参数:每页条数
	paginator = Paginator(book_list, 10)
	
  	# Paginator对象的属性和方法
	print(paginator.per_page)  # 每页显示的条数 -- 10
	print(paginator.count)  # 总条数,总共要分页多少条数据
	print(paginator.num_pages)  # 总页码数
	print(paginator.page_range)  # 页码的生成器[1,2,3....10]
	page= paginator.page(2)
	
 	# 每一页的对象page,属性和方法
	print(page.has_next())  # 是否有下一页
	print(page.next_page_number())  # 下一页页码
	print(page.has_previous())  # 是否有上一页
	print(page.previous_page_number())  # 上一页的页码,没有就报错
	print(page.object_list)  # 当前页的数据
	print(page.number)  # 当前页数
	return render(request, 'func139_1.html', locals())

2 分页器的简单使用

## views.py

def index(request):
    # 需要的第三个参数
    page_num_int=int(request.GET.get('page',1))
    book_list = models.Book.objects.all()
    paginator = Paginator(book_list, 10)

    # 需要的第一个参数:页码的生成器 [1,2,3,4,5,6,7,8,9,10]
    page_range = paginator.page_range
    # 需要的第二个参数,去到某一页的page对象
    page = paginator.page(page_num_int)
    return render(request, 'index.html', {'page_range':page_range,'page':page,'page_num_int':page_num_int})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <title>Title</title>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <table class="table">
                <thead>
                <tr>
                    <th>id</th>
                    <th>名字</th>
                    <th>价格</th>
                </tr>
                </thead>
                <tbody>


                {% for book in page.object_list %}
                    <tr>
                        <td>{{ book.id }}</td>
                        <td>{{ book.name }}</td>
                        <td>{{ book.price }}</td>
                    </tr>
                {% endfor %}
                </tbody>

            </table>

            <div class="text-center">
                <nav aria-label="Page navigation">
                    <ul class="pagination">

                        {% if page.has_previous %}
                            <li>
                                <a href="/?page={{ page.previous_page_number }}" aria-label="Previous">
                                    <span aria-hidden="true">&laquo;</span>
                                </a>
                            </li>
                        {% else %}
                            <li class="disabled">
                                <a href="" aria-label="Previous">
                                    <span aria-hidden="true">&laquo;</span>
                                </a>
                            </li>
                        {% endif %}
                        {% for page_num in page_range %}
                            {% if page_num_int == page_num %}
                                <li class="active"><a href="/?page={{ page_num }}">{{ page_num }}</a></li>
                            {% else %}
                                <li><a href="/?page={{ page_num }}">{{ page_num }}</a></li>
                            {% endif %}

                        {% endfor %}


                        {% if page.has_next %}
                            <li>
                                <a href="/?page={{ page.next_page_number }}" aria-label="Next">
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>
                        {% else %}
                            <li class="disabled">
                                <a href="" aria-label="Next">
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>
                        {% endif %}
                    </ul>
                </nav>
            </div>
        </div>
    </div>


</div>
</body>
</html>

3 分页器进阶使用

# 最多显示前5 后5 和当前,总共11个页码,如果少于11,全部显示出来

#逻辑分析 
	显示左5,右5,总共11个页,
    1 如果总页码大于11
        1.1 if 当前页码减5小于1,要生成112的列表(顾头不顾尾,共11个页码)
            page_range=range(1,12)
        1.2 elif 当前页码+5大于总页码,生成当前页码减10,到当前页码加1的列表(顾头不顾尾,共11个页码)
            page_range=range(paginator.num_pages-10,paginator.num_pages+1)
        1.3 else 生成当前页码-5,到当前页码+6的列表
            page_range=range(current_page_num-5,current_page_num+6)
    2 其它情况,生成的列表就是pageinator的page_range
        page_range=paginator.page_range
# views.py
def index(request):
    # 需要的第三个参数
    page_num_int = int(request.GET.get('page', 1))
    book_list = models.Book.objects.all()
    paginator = Paginator(book_list, 1)

    # 需要的第一个参数:页码的生成器 [1,2,3,4,5,6,7,8,9,10]
    # page_range = paginator.page_range
    if paginator.num_pages > 11:

        # 当前条件符合了以后,有三种情况
        if page_num_int - 5 < 1:
            page_range = range(1, 11)
        elif page_num_int + 5 > paginator.num_pages:
            page_range = range(paginator.num_pages - 10, paginator.num_pages + 1)
        else:
            page_range = range(page_num_int - 5, page_num_int + 5)
    else:
        page_range = paginator.page_range
    # 需要的第二个参数,去到某一页的page对象
    page = paginator.page(page_num_int)
    return render(request, 'index.html', {'page_range': page_range, 'page': page, 'page_num_int': page_num_int})
模版文件同上

4 form组件介绍

1 注册功能,登陆功能,前段需要校验(字段长度,邮箱是否合法...)
2 前端校验可以没有,后端校验是必须的,使用传统方式,if判断写的很多
3 借助于forms组件 可以快速实现字段的校验()
# app01下新建myforms.py
from django import forms


# 写一个类,继承forms.Form 写字段
class MyForm(forms.Form):
	# 校验这个字段,必填,最大长度32,最小长度是3
	name = forms.CharField(required=True, max_length=32, min_length=3, label='用户名')
	# 校验邮箱地址
	email = forms.EmailField(label='邮箱')
  # 校验年龄,最小0最大200
	age= forms.IntegerField(max_value=200,min_value=0,label='年龄')

# 一些问题:
# 1 错误是英文的
# 2 错误信息是标签
# 3 更复杂的校验,name必须有大写,数字

5 form组件校验数据

# views.py

def func139_2(request):
	# 数据可以是从前端传过来的,也可以是后端自己的数据
	# 我现在有以下数据
	data = {'name': 'lq', 'email': "3333"}
	# 校验数据是否合法
	# 实例化得到form对象,把要校验的数据传入
	form = myforms.MyForm(data=data)
	# 校验数据
	if form.is_valid():  # 返回True或者False
		print('校验成功')
		# 校验通过的数据:
		print(form.cleaned_data)
	else:
		# 拿出校验通过的数据
		print(form.cleaned_data)
		print('校验失败')
		# 哪个字段失败了?
		print(form.errors)
		# 重写了errors的__str__
		print(type(form.errors))
		print(form.errors.as_json())
		print(form.errors.as_data())
		# form.errors.as_ul()是为了渲染模版
	return HttpResponse('ok')

6 forms渲染模版功能

## views.py
def register(request):
    if request.method=='GET':
        form=myforms.MyForm()
        return render(request,'register.html',{'form':form})
    elif request.method=='POST':
        # 数据校验
        form=myforms.MyForm(request.POST)
        if form.is_valid():
            print('校验通过,存数据库')
        else:
            print(form.errors.as_data())
            print('校验失败,返回错误')
        return HttpResponse('ok')
# 模版文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<hr>
<h1>手动创建模板</h1>
<form action="" method="post">
    <p>用户名:<input type="text" name="name"></p>
    <p>邮箱:<input type="text" name="email"></p>
    <p>年龄:<input type="text" name="age"></p>
    <p><input type="submit" value="提交"></p>
</form>

<hr>
<h1>半自动渲染模板1</h1>
<form action="" method="post">
    <p>用户名:{{ form.name }}</p>
    <p>邮箱:{{ form.email }}</p>
    <p>年龄:{{ form.age }}</p>
    <p><input type="submit" value="提交"></p>
</form>

<h1>半自动渲染模板2(用的最多)</h1>
<form action="" method="post">
    <p>{{ form.name.label }}--{{ form.name }}</p>
    <p>{{ form.email.label }}---{{ form.email }}</p>
    <p>{{ form.age.label }}---{{ form.age }}</p>
    <p><input type="submit" value="提交"></p>
</form>

<h1>半自动渲染模板3(用的最多)</h1>
<form action="" method="post">
    {% for foo in form %}
       <p>{{ foo.label }} :{{ foo }}</p>
    {% endfor %}

    <p><input type="submit" value="提交"></p>
</form>

<h1>全自动(了解)</h1>
<form action="" method="post">
{#    {{ form.as_ul }}#}
    {{ form.as_p }}
{#    <table>#}
{#        {{ form.as_table }}#}
{#    </table>#}

    <p><input type="submit" value="提交"></p>
</form>
</body>
</html>

作业

## 0 整理笔记
## 1 分页器实现通过传入某一页,和该页大小实现分页器

## 2 用户注册: 通过forms实现半自动的渲染模板,校验字段,校验通过存到user(bootstrap样式)

## 3 (拓展)研究一些form如何校验更复杂的校验,name必须有大写,小写,数字,错误信息的中文显示

# 可以自定义中文显示 或者 在settings里改语言
name = forms.CharField(min_length=4, label="姓名", error_messages={"min_length": "太短了", "required": "该字段不能为空!"})

## 4 拓展cookie,session,token ,jwt
from django import forms
from django.core.exceptions import ValidationError
from app01 import models
class EmpForm(forms.Form):
    name = forms.CharField(min_length=5, label="姓名", error_messages={"required": "该字段不能为空!",
                                                                     "min_length": "用户名太短。"})
    age = forms.IntegerField(label="年龄")
    salary = forms.DecimalField(max_digits=5, decimal_places=2, label="工资")
    r_salary = forms.DecimalField(max_digits=5, decimal_places=2, label="请再输入工资")


    def clean_name(self):  # 局部钩子
        val = self.cleaned_data.get("name")


        if val.isdigit():
            raise ValidationError("用户名不能是纯数字")
        elif models.Emp.objects.filter(name=val):
            raise ValidationError("用户名已存在!")
        else:
            return val

    def clean(self):  # 全局钩子 确认两次输入的工资是否一致。
        val = self.cleaned_data.get("salary")
        r_val = self.cleaned_data.get("r_salary")


        if val == r_val:
            return self.cleaned_data
        else:
            raise ValidationError("请确认工资是否一致。")
views.py 文件代码:

app01/views.py
def add_emp(request):
    if request.method == "GET":
        form = EmpForm()  # 初始化form对象
        return render(request, "add_emp.html", {"form":form})
    else:
        form = EmpForm(request.POST)  # 将数据传给form对象
        if form.is_valid():  # 进行校验
            data = form.cleaned_data
            data.pop("r_salary")
            models.Emp.objects.create(**data)
            return redirect("/index/")
        else:  # 校验失败
            clear_errors = form.errors.get("__all__")  # 获取全局钩子错误信息
            return render(request, "add_emp.html", {"form": form, "clear_errors": clear_errors})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值