Web框架之Django进阶篇

一、Django内置分页

 在Django中需要使用内置的分页时,需要导入下面的模块。

from django.shortcuts import render
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger

user_list = []
for i in range(1,999):
    temp = {'name':'root'+str(i),'age':i}
    user_list.append(temp)

#Django内置分页
def index1(request):
    
    current_page=request.GET.get('p')
    paginator = Paginator(user_list,10)
    #per_page:每页显示条目数量
    #count:   数据总个数
    #num_page:总页数
    #page_range:总页数的索引范围,如(1,10),(1,200)
    #page:page对象
    try:
        posts=paginator.page(current_page)
        #has_next               是否有下一页
        #next_page_number       下一页页码
        #has_previous           是否有上一页
        #previous_page_number   上一页页码
        #object_list            分页之后的数据列表
        #number                 当前页
        #paginator              paginator对象
    except PageNotAnInteger:
        posts=paginator.page(1)
    except EmptyPage:
        posts=paginator.page(paginator.num_pages)
    return render(request,'index1.html',{'posts':posts})
Views
<ul>
        {#{% for row in posts %}#}  {# 一样效果 #}
        {% for row in posts.object_list %}
            <li>{{ row.name }}-{{ row.age }}</li>
        {% endfor %}

        {% include 'include/pager.html' %}      {# 引用include目录下的页面跳转 #}

    </ul>

pager.html:
{% if posts.has_previous %}
    <a href="/index1.html?p={{ posts.previous_page_number }}">上一页</a>
{% else %}
    <a href="javascript:;">上一页</a>
{% endif %}
{% if posts.has_next %}
    <a href="/index1.html?p={{ posts.next_page_number }}">下一页</a>
{% endif %}

<span>
    {{ posts.number }}/{{ posts.paginator.num_pages }}
</span>
HTML

   在Django自带的内置分页中,由于没有显示页码的功能,所以当我们需要使用当页码功能时,就需要修改源码了,但是并不推荐这样做,因为如果其他项目中需要页码功能时又要我们修改源码,所以这里我们可以自定制一个页码功能,当我们需要时调用就ok了。

from django.shortcuts import render
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
user_list = []
for i in range(1,666):
    temp = {'name':'root'+str(i),'age':i}
    user_list.append(temp)

# Create your views here.

# ****************************************Django分页**********************************************

#自定制类分页(显示页码)
class CustomPaginator(Paginator):
    def __init__(self,current_page,per_pager_num,*args,**kwargs):
        # 当前页
        self.current_page=int(current_page)
        # 显示最多的页码数量 11
        self.per_pager_num=int(per_pager_num)
        super(CustomPaginator,self).__init__(*args,**kwargs)    #运用继承Paginator的功能

    def pager_num_range(self):
        #当前页
        #self.current_page
        #最多页码数量
        # self.per_pager_num
        #总页数
        # self.num_pages
        if self.num_pages < self.per_pager_num:     #条件1:当总页数小于要显示的页码时      *
            return range(1,self.num_pages+1)
                                                    # 条件2:当总页数大于要显示的页码时     **
        part = int(self.per_pager_num/2)            #中间页码                               **
        if self.current_page <= part:               #当前所在的页码小于中间页码,显示1-11页 **
            return range(1,self.per_pager_num+1)
        if (self.current_page + part) > self.num_pages:     #条件3:当页码到总页数时,不能再增加页码   ***
            return range(self.num_pages-self.per_pager_num+1,self.num_pages+1)
        return range(self.current_page-part,self.current_page+part+1) #当前所在页码大于中间页码,需要改变页码 **

#Django内置分页
def index1(request):
    current_page=request.GET.get('p')
    paginator = CustomPaginator(current_page,11,user_list,10)   #每页10个数据
    #per_page:每页显示条目数量
    #count:   数据总个数
    #num_page:总页数
    #page_range:总页数的索引范围,如(1,10),(1,200)
    #page:page对象
    try:
        posts=paginator.page(current_page)
        #has_next               是否有下一页
        #next_page_number       下一页页码
        #has_previous           是否有上一页
        #previous_page_number   上一页页码
        #object_list            分页之后的数据列表
        #number                 当前页
        #paginator              paginator对象
    except PageNotAnInteger:
        posts=paginator.page(1)
    except EmptyPage:
        posts=paginator.page(paginator.num_pages)
    return render(request,'index1.html',{'posts':posts})
Django页码扩展
{#***********************************Django内置分页*********************************#}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        {#{% for row in posts %}#}  {# 一样效果 #}
        {% for row in posts.object_list %}
            <li>{{ row.name }}-{{ row.age }}</li>
        {% endfor %}

        {% include 'include/pager.html' %}      {# 引用include目录下的页面跳转 #}

    </ul>
</body>
</html>

pager.html:
{% if posts.has_previous %}
    <a href="/index1.html?p={{ posts.previous_page_number }}">上一页</a>
{% else %}
    <a href="javascript:;">上一页</a>
{% endif %}

{#显示页码,这里调用的是自定制类中的pager_num_range方法#}
{% for i in posts.paginator.pager_num_range %}
    {% if i == posts.number %}
        <a style="font-size: 20px" href="/index1.html?p={{ i }}">{{ i }}</a>
    {% else %}
        <a href="/index1.html?p={{ i }}">{{ i }}</a>
    {% endif %}
{% endfor %}

{% if posts.has_next %}
    <a href="/index1.html?p={{ posts.next_page_number }}">下一页</a>
{% endif %}

{#当前在多少页#}
<span>
    {{ posts.number }}/{{ posts.paginator.num_pages }}
</span>
页码扩展HTML部分

 

二、Form组件

一、简单概括一下Form组件的两个功能:

  ①对用户请求的验证(需要导入模块)

  ②生成HTML

    - 对用户请求的验证
        - Ajax
        - Form
    - 生产HTML代码
    
    a.创建一个类
    b.类中创建字段(包含正则表达式)
    c.GET
        obj = Fr()
        obj.user => 自动生成HTML
    d.POST
        obj = Fr(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)    //字典形式的数据
        else:
            print(obj.errors)            //错误信息
            return render(request,'f1.html',{'obj':obj})
如何使用Form组件思路
from django.shortcuts import render,redirect
from django.shortcuts import HttpResponse
from django import forms
from django.forms import fields
# Create your views here.
class f1Form(forms.Form):
    user = forms.CharField(required=True,min_length=2,max_length=8,error_messages={
        'required':'用户名不能为空',
        'max_length':'长度太长了',
        'min_length':'长度太短了'
    })
    pwd = forms.CharField(required=True,min_length=6,max_length=20,error_messages={
        'required': '密码不能为空',
        'max_length': '长度太长了',
        'min_length': '长度太短了'
    })
    age = forms.IntegerField(required=True,error_messages={'required':'年龄不能为空','invalid':'格式错误哦'})
    email = forms.EmailField(required=True,error_messages={'required':'邮件不能为空','invalid':'格式错误哦'})

def f1(request):
    if request.method == "GET":
        obj = f1Form()
        return render(request,'f1.html',{'obj':obj})
    else:
        obj = f1Form(request.POST)      #用户提交数据
        if obj.is_valid():
            print('验证成功',obj.cleaned_data)        #提交的数据,字典形式
            return redirect('http://baidu.com')
        else:
            print('验证失败',obj.errors)
            return render(request,'f1.html',{'obj':obj})
验证用户请求(创建类)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Form验证</title>
</head>
<body>
<form action="/f1.html" method="post">
    <p>{{ obj.user }}{{ obj.errors.user.0 }}</p>    {# 第一个是Form组件自动生成的HTML,第二个是错误信息 #}
    <p>{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p>
    <p>{{ obj.age }}{{ obj.errors.age.0 }}</p>
    <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
    <p><input type="submit" value="提交"></p>
</form>
</body>
</html>
HTML部分

二、Form组件的一些字段、生成HTML插件、以及验证功能的扩展:

https://www.cnblogs.com/ray-h/p/10184079.html

 

三、序列化

Django中的序列化主要应用在用户对数据库请求数据时发送给前端的数据,特别的Ajax请求一般返回的为Json格式。

数据库返回的数据有3种类型:

       ① 对象 <QuerySet([ obj , obj , obj ])>

  ② 字典 <QuerySet([ { 'id':1,'user':'Ray' } , { 'id':2,'user':'Alex' }  , { 'id':1,'user':'Jack' } ])>

  ③ 元祖 <QuerySet([ (1,'Ray') , (2,'Alex') , (3,'Jack') ])>

例子:

Ajax请求数据时获得 -> success:function(arg){},此时需要根据arg的状态判断是否请求成功,假如后台使用字典的形式传送给前端

==> response = {'stutas':True , 'msg':None}

- 需要把cleaned_data中的数据序列化成字符串
        A.对象(QuerySet[obj,obj,obj])
            - 使用模块
                ret = {'stutas':True,'data':None}
                from django.core import serialziers
                user_list = UserInfo.objects.all()
                ret['data'] = serializers.serializer("json",user_list)

        B.字典(QuerySet[{'id':1,'user':'ray1'},{'id':2,'user':'ray2'},{'id':3,'user':'ray3'}])
            - 使用list
                user_list = UserInfo.objects.all()
                ret['data'] = list(user_list)

        C.元祖(QuerySet[(1,'ray1'),(2,'ray2')])
            - 使用list
                user_list = UserInfo.objects.all()
                ret['data'] = list(user_list)

    - 总结:
        - ①上面的序列化只能把返回给前端ret字典中的数据 ==> ret['data']序列化成字符串;
        - ②然后数据返回给前端Ajax获取时还是需要把ret字典转换为前端识别的json字符串
            ==> return HttpResponese(json.dumos(ret))

  

posted @ 2018-12-25 23:19  rayh  阅读(122)  评论(0)    收藏  举报