利用Ajax技术实现页面的局部刷新,降低服务器的压力。
Ajax是爬虫、前端、后台不分家的地方。之前遇到过蛮多的,所以自己实现一下。做了一段时间的东西了,此处做一下汇总。
此处两个demo:
- xhr翻页
- 实现购物车功能(Ajax配合session)
- 搜索提示
1.xhr翻页
动态从后台数据库读取一部分数据,并作为json返回,前端用js遍历出来
# urls.py
from django.urls import path
from ajax_data.views import *
urlpatterns = [
path('add/', insert_into_databases),
path('index/', index),
path('get_json/', send_json),
]
# views.py
from django.shortcuts import render, HttpResponse
from .models import AjaxData
import random
from random import randint
import string
import json
# Create your views here.
# 生成随机数据并插入到数据库
def insert_into_databases(request):
for i in range(20):
AjaxData.objects.create(
title='数学_' + ''.join([random.choice(string.ascii_letters) for i in range(5)]),
price=randint(10, 30),
comments=randint(100, 666),
)
return HttpResponse('Successfully insert')
def index(request):
return render(request, 'dynamic_web_page.html')
def send_json(request):
offset = request.GET.get('offset')
print(type(offset), offset)
x = int(offset)
books = AjaxData.objects.all()[x: x + 5]
print(books)
# 构造字典,下面转换为json
json_data = {'book_list': []}
for book in books:
_dict = {'title': book.title, 'price': book.price, 'comments': book.comments}
json_data['book_list'].append(_dict)
# 将python对象转换为json对象返回给js进行处理
return HttpResponse(json.dumps(json_data), content_type='application/json')
# dynamic_web_page.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/popper.js/1.12.5/umd/popper.min.js"></script>
<script src="https://cdn.bootcss.com/popper.js/1.12.5/umd/popper.min.js"></script>
<script src="http://apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<header>商品列表</header>
<div> </div>
<div class="get-json"></div>
<form action="/get_json/" method="get">
<ul class="pagination">
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
{# 如果没写form表单,直接href="/get_json/"的话,是不会触发js事件的 #}
{# 要触发js事件:1. 添加form表单 2. 给href属性指定一个实名函数,在实名函数里面写方法 #}
<li class="page-item"><a class="page-link" href="#">4</a></li>
{# <li class="page-item"><a class="page-link" href="javaScript:send()">4</a></li>#}
</ul>
</form>
<footer>页脚</footer>
<script>
function send(){
$.get("/get_json/", {'offset': '4'}, function (json) {
console.log(json);
for (var i = 0; i < json['book_list'].length; i++) {
var title = "<p>" + json['book_list'][i]['title'];
var price = json['book_list'][i]['price'];
var comments = json['book_list'][i]['comments'] + "</p>";
var divElement = "<div>" + title + " ¥" + price + " 评论数:" +comments + "</div>";
console.log(divElement);
$('div.get-json').append(divElement);
}
});
}
$(document).ready(function () {
//首页的数据
$.get("/get_json/", {'offset': '0'}, function (json) {
console.log(json);
for (var i = 0; i < json['book_list'].length; i++) {
var title = "<p>" + json['book_list'][i]['title'];
var price = json['book_list'][i]['price'];
var comments = json['book_list'][i]['comments'] + "</p>";
var divElement = "<div>" + title + " ¥" + price + " 评论数:" +comments + "</div>";
console.log(divElement);
$('div.get-json').append(divElement);
}
});
//根据按钮的值进行Ajax请求并遍历json
var liList = $('li.page-item');
for (var i = 0; i < liList.length; i++) {
$(liList[i]).click(function () {
$('div.get-json').empty();
var innerText = $(this).children('a').text();
console.log(innerText);
var offset = (parseInt(innerText) - 1) * 5;
console.log(offset);
$.get("/get_json/", {'offset': offset}, function (json) {
console.log(json);
for (var i = 0; i < json['book_list'].length; i++) {
var title = "<p>" + json['book_list'][i]['title'];
var price = json['book_list'][i]['price'];
var comments = json['book_list'][i]['comments'] + "</p>";
var divElement = "<div>" + title + " ¥" + price + " 评论数:" +comments + "</div>";
console.log(divElement);
$('div.get-json').append(divElement);
};
})
});
}
});
</script>
</body>
</html>
2.实现购物车功能
两个页面,第一个可以自由的选择商品。第二个页面可以自由移除商品,并使用js进行页面元素的删除。为了只跑一次SQL,提升性能,此处使用session来保存用户所选择的商品。
# urls.py
from django.contrib import admin
from django.urls import path, re_path
from .views import *
urlpatterns = [
path('shopping/', shopping, name='shopping'),
path('selected_show/', selected_show, name="select_show"),
path('parse_shopping/', parse_shopping, name='parse_shopping'),
re_path('del_session/product_id=(\d+)/', delete_session, name='del_session'),
path('del_session_by_ajax/', del_session_by_ajax)
]
# views.py
def shopping(request):
return render(request, 'shopping.html')
def parse_shopping(request):
# 这个方法一次只能添加一个商品
print(request.session.items())
product = request.POST.get('product', '')
price = request.POST.get('price', '')
product_id = request.POST.get('id', '')
print(product, price, product_id)
# 用 product_id 标识 该商品所对应的session
key_name = 'product_' + product_id
if product_id:
# product_list = request.session.get('product', [])
# if not product in product_list:
# product_list.append({'id': product_id, 'product': product, 'price': price})
request.session[key_name] = {'id': product_id, 'product': product, 'price': price}
return HttpResponse(f'商品:{product} 价格:{price}元 id:{product_id}')
else:
return redirect('/')
def selected_show(request):
session_keys = request.session.items()
print(session_keys)
return render(request, 'del_product.html', locals())
"""
def delect_session(request):
price_data = request.GET.get('id_price')
print(price_data)
memorize_product_name = 'None'
# for key, value in request.session.items():
# print(key, value)
for key, value in request.session.items():
if value.endswith(price_data):
memorize_product_name = key
del request.session[key]
return HttpResponse(memorize_product_name + '删除成功')
"""
def delete_session(request, product_id):
print(product_id)
for key, value in request.session.items():
if value.get('id') == product_id:
del request.session[key]
break # 会出现错误 - > dictionary changed size during iteration , 加一个break就好了
session_keys = request.session.items()
return render(request, 'show_cart_new.html', locals())
# return redirect('select_show', locals())
def del_session_by_ajax(request):
product_id = request.POST.get('product_id', '')
for key, value in request.session.items():
if value.get('id') == product_id:
del request.session[key]
break
return HttpResponse('id为{}的商品已被移除购物车'.format(product_id))
前端页面
# shopping.html 购物页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>shopping</title>
<style>
.fix-here {
{#margin-left: 300px;#}
}
</style>
</head>
<body>
{#{% url 'parse_shopping' %}#}
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<ul id="first" style="list-style: none;">
<li><p class="product">A商品</p><p class="price">30</p><a href="#" id="1">点击抢购</a></li>
<li><p class="product">B商品</p><p class="price">40</p><a href="#" id="2">点击抢购</a></li>
<li><p class="product">C商品</p><p class="price">50</p><a href="#" id="3">点击抢购</a></li>
<li><p class="product">D商品</p><p class="price">60</p><a href="#" id="4">点击抢购</a></li>
</ul>
<a href="{% url 'select_show' %}">进入购物车</a>
<br>
<div>
已选购商品数
<span id="dynamic-number">0</span>
</div>
<script>
var num = 0;
var myUl = document.getElementById('first');
var liList = myUl.getElementsByTagName('li');
var len = liList.length;
for (var i = 0; i < len; i++) {
liList[i].onclick = function (ele) {
var element = ele.target;
console.log(element);
num += 1;
alert('添加商品成功');
$('dynamic-number').innerText = num;
var productPrice = $(element).prev().text();
var productName = $(element).prev().prev().text();
var productId = $(element).attr('id');
$.ajax({
url:'{% url "parse_shopping" %}',
type:'POST',
data: {'product': productName, 'price': productPrice, 'id': productId},
success: function (data) {
alert(data);
}
});
};
}
</script>
</body>
</html>
# del_product.html 购物车
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>show cart</title>
</head>
<body>
<ul>
{% for session_key, value_dict in session_keys %}
<li>{{ value_dict.product }} {{ value_dict.price }}元</li>
<button class="del-it" id="{{ value_dict.id }}">移除商品</button>
{% endfor %}
</ul>
<div>123</div>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
/*
var btnList = document.getElementsByClassName('del-it');
for (var i = 0; i < btnList.length; i++) {
var element = $(btnList[i]);
element.onclick = function () {
var inner_text = this.prev().text();
var pattern = /.*?(\d{2})元/g;
var result = inner_text.match(pattern);
this.remove();
this.prev().remove();
};
}
*/
var btnList = document.getElementsByClassName('del-it')
for(var i = 0; i < btnList.length; i++) {
// 遍历给元素附上事件
$(btnList[i]).click(function() {
var productId = $(this).attr("id");
$(this).prev().remove();
$(this).remove();
$.ajax({
url: "/del_session_by_ajax/",
data: {"product_id": productId},
type: "POST",
success: function (data) {
// Ajax请求成功以后进行元素的删除
alert(data);
}
})
});
}
</script>
</body>
</html>
3.实现搜索提示
设置事件监听键盘的起落,动态发送已经键入的关键词到后台,后台进行数据库查询并返回json,然后用js遍历json
urls.py
from django.urls import path
from Ajax_search.views import search_name
from .views import index
urlpatterns = [
path('Fsearch/', search_name),
path('', index),
]
# views.py
from django.shortcuts import render, HttpResponse
from Ajax_search.models import AjaxSearch
import json
# Create your views here.
def search_name(request):
keyword = request.GET.get('keyword', '')
name_list = AjaxSearch.objects.filter(have_been_searched__contains=keyword)
# 将QuerySet对象的列表list一下,这样才可以处理里面的对象了
json_source = list(map(lambda item: item.have_been_searched, name_list))
return HttpResponse(json.dumps(json_source), content_type='application/json')
html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<body>
<div style="margin-top: 300px;margin-left: 520px;">
<form action="/Fsearch/" method="get" style="margin: auto 0;">
请输入要查询的关键字:<br/>
<input type="text" id="search-text" name="keyword"><button type="button" id='search-button'>搜索</button>
<p><span id='search-result'></span></p>
</form>
</div>
<script src="http://apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#search-text").keyup(function(){
var keyword = $("#search-text").val();
//当表单的值是一个空字符串,并且是最后删除完东西的时候
if (keyword == '') {
console.log('The form value is empty.');
return;
}
$.get("/Fsearch/",{'keyword': keyword}, function(data){
for (var i = 0;i < data.length; i++) {
$('#search-result').append(data[i]+'<br/>')
}
});
});
$('#search-text').keydown(function(){
$('#search-result').empty();
});
$('#search-text').blur(function(){
$('#search-result').empty();
});
});
</script>
</body>
</html>
事实上,知识之间都是有交汇的地方的。学得精才是正道。