一、利用前后端交互实现分页功能
我们知道,使用django时,如果想让数据库中的信息在前端页面显示时,所有信息会全部展示出来,这显然与我们生活中所见到的app不符。为了达到将数据库中的数据进行分批次显示这一需求,便要我们对后端的数据进行处理,每次取出固定的条数。
假设以班级管理为例,我们要拿到班级信息,我们先配置好django的环境:
第一步:设置好url
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('classes.html/', views.handle_classes),
]
第二步,创建班级数据库:
from django.db import models
class Classes(models.Model):
caption = models.CharField(max_length=32)
第三步,事先导入jquery数据包,将其存放在主目录新建的static文件夹中(前端实现需要用到jquery知识):
第四步:由于django2.2版本在创建app的时候,会自动在INSTALLED_APPS中添加app的名称,因此无需再次添加app的名字。项目中需要利用form表单提交,预先将MIDDLEWARE中的csrf注释掉,配置setting文件夹:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
STATIC_URL = '/static/'
STATICFILES_DIRS=(
os.path.join(BASE_DIR,"static"),
)
准备工作已经全部完成,下面在终端输入命令,在数据库中创建班级列表,并启动服务端:
第一步:python manage.py makemigrations
第二步:python manage.py migrate
第三步(启动服务端):python manage.py runserver 8080(端口号随意)
为了使大家更好的理解前后端的交互,我先将其他代码删掉,只留下分页所需的前后端交互,下面是在body中插入的前端代码:
<div class="pagination">
{{ str_pager }}
</div>
因为分页是几乎所有前后端项目中都必备的需求,我们将将其功能封装为模块,放入主目录下新建的utils文件夹下:
下面先附上分页代码:
class PagerHelper:
def __init__(self,total_count,current_page,base_url,per_page=10):
self.total_count = total_count #封装总共多少条信息
self.current_page = current_page #封装当前页面,以当前页面为基础(假设为n页),显示总页面的n-m~~n+m页
self.base_url = base_url #封装需要分页的url
self.per_page = per_page #封装每页中显示的数据量
@property
def db_start(self):
return (self.current_page -1) * self.per_page # 设置显示到页面中的起始数据的编号
@property
def db_end(self):
return self.current_page * self.per_page # 设置显示到页面中的结尾数据的编号
def total_page(self):
v, a = divmod(self.total_count, self.per_page) #divmod() 函数把除数和余数运算结果结合起来
if a != 0:
v += 1
return v
def pager_str(self):
v = self.total_page()
pager_list = []
if self.current_page == 1: #如果当前页面为1,那么不能再往前去取
pager_list.append('<a href="javascript:void(0);">上一页</a>')
else:
pager_list.append('<a href="%s?p=%s">上一页</a>' % (self.base_url, self.current_page - 1,))
# 6,1:12
# 7,2:13
if v <= 11: # 每次显示前后5页,那么如果总页面小于11,则第一页固定为1
pager_range_start = 1
pager_range_end = v
else:
if self.current_page < 6:
pager_range_start = 1
pager_range_end = 11 + 1
else:
pager_range_start = self.current_page - 5
pager_range_end = self.current_page + 5 + 1
if pager_range_end > v:
pager_range_start = v - 10
pager_range_end = v + 1
for i in range(pager_range_start, pager_range_end):
if i == self.current_page:
pager_list.append('<a class="active" href="%s?p=%s">%s</a>' % (self.base_url, i, i,))
else:
pager_list.append('<a href="%s?p=%s">%s</a>' % (self.base_url, i, i,))
if self.current_page == v:
pager_list.append('<a href="javascript:void(0);">下一页</a>')
else:
pager_list.append('<a href="%s?p=%s">下一页</a>' % (self.base_url, self.current_page + 1,))
pager = "".join(pager_list) #将列表中的字符串,进行切割变成一个个的<a>标签
return pager
这里,有一个点有些小伙伴可能不太清除,那就是装饰器的作用:@property
可以参考这篇文章:装饰器的解释
这里我简单的可以将其概括为:将get/set方法变成属性赋值,可以直接进行调用
再附上后端代码:
from django.shortcuts import render,redirect,HttpResponse
from app01 import models
from django.utils.safestring import mark_safe
from django import views
import json
def handle_classes(request):
if request.method == "GET":
# 获取所有的班级列表
# models.Classes.objects.create(caption='全栈一班')
# models.Classes.objects.create(caption='全栈二班')
# models.Classes.objects.create(caption='全栈三班')
current_page=request.GET.get('p',1)
current_page=int(current_page)
total_count = models.Classes.objects.all().count()
from utils.page import PagerHelper
obj=PagerHelper(total_count,current_page,'/classes.html',10) #创建分页对象
pager = obj.pager_str()
cls_list = models.Classes.objects.all()[obj.db_start:obj.db_end]
current_user = request.session.get('username')
return render(request,
'classes.html',
{'username': current_user, 'cls_list': cls_list,'str_pager':mark_safe(pager)})
elif request.method == "POST":
# Form表单提交的处理方式
# Ajax
import json
response_dict = {'status': True, 'error': None, 'data': None}
return HttpResponse(json.dumps(response_dict))
大家查看一下效果图:
二、利用最基础的CSS、JS、jQuery知识,实现点赞效果
点击够,赞的效果会发生变化,这里我们不作考虑。难点的地方在于怎么能有一个+1渐渐的浮现出来先附上效果图:
上述配置jQuery已经讲过,这里不再赘述,先配置urls和views:
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('test.html/', views.test),
]
def test(request):
return render(request,"test.html")
下面是前端页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.item{
height: 100px;
border: solid 1px deepskyblue;
}
.zan{
height: 30px;
width: 30px;
background-color: darkgray;
color: white;
margin-top: 35px; // 让文字赞居中
cursor: pointer;
position: relative;
}
.zan span{
position: absolute; //将创建的+1 在文字赞的旁边显示
}
</style>
</head>
<body>
<div class="item">
<div class="zan">赞</div>
</div>
</body>
<script src="/static/jquery-3.3.1.js"></script>
<script>
$(function () {
$('.zan').click(function () { // 绑定点击事件
var fz = 12;
var tp = 5;
var lp = 5;
var op = 1;
var tag = document.createElement('span'); //当点击赞的时候,创建span标签,内容显示为‘+1’
tag.innerHTML = "+1";
tag.style.color = "red";
tag.style.fontSize = fz + 'px';
tag.style.top = tp + 'px';
tag.style.left = lp + 'px';
tag.opacity = op;
$(this).append(tag);//当前的标签下,添加tag标签
var obj = setInterval(function () { //需求的关键处,设置一个定时器
fz += 5;
tp -= 5;
lp += 5;
op -= 0.2;
tag.style.fontSize = fz + 'px';
tag.style.top = tp + 'px';
tag.style.left = lp + 'px';
tag.opacity = op; //将透明度逐渐变低
if (op <0){ //当透明度变为0的时候,删除定时器和tag标签
clearInterval(obj);
$(tag).remove();
}
},100)//每100毫秒执行一次
})
})
</script>
</html>