Python学习笔记:6.3.5 json数据格式与ajax请求

前言:本文是学习网易微专业的《python全栈工程师 - Flask高级建站》课程的笔记,欢迎学习交流。同时感谢老师们的精彩传授!

一、课程目标
  • json数据格式
  • ajax提交
  • jQuery的ajax实现
二、详情解读
2.1.json数据格式

json格式是一种字符串格式,比如:

'[{"upload": 1, "fileName": "foo.jpg", "url": "/files/foo.jpg"}]'

他是一个字符串,但是看上去就好像是列表与字典组成的结构。

为什么使用json格式:
在网页访问期间,前端只能向后端发送字符串,不能发送其他任何类型的数据,比如数组,对象。通过把json对象转换为字符串格式,就可以通过互联网传输,而且无论js,python,java,php都支持json的编码与解码。

2.1.1.python对json的支持

json模块:
1.导入模块:import json
2.将对象转换为json字符串 - json.dumps()
3.将json字符串转换为python列表与数组 - json.loads()

2.1.2.js对json的支持

js提供了一个JSON对象
1.将对象转换为json字符串 - JSON.stringify()
2.将json字符串转换为js的数组与对象 - JSON.parse()

2.2.ajax数据提交
2.2.1.ajax技术

ajax技术称为无刷新数据提交,表单提交过程会带来整个页面的刷新,如果发生错误,卡顿,对用户的体验很不好。现代浏览器都支持一种称不xhr的对象向后台提交数据。

实操:(这部分是测试用的)
Step1:新建文件夹templates/ajax,并在ajax目录下创建文件form.html,写入以下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% if message %}
    {{ message }}
{% endif %}
<form action="" method="post">
    <input type="text" name="name">
    <input type="password" name="password" id="password">
    <input type="submit" name="submit" value="提交">
</form>
</body>
</html>

Step2:在app.py中添加test_form()视图函数:

# 测试ajax的异步提交
@app.route('/form', methods=['GET', 'POST'])
def test_form():
    from time import sleep
    message = None
    if request.method == 'POST':
        pass
        sleep(3)
        message = '提交数据有问题,失败'
    return render_template('ajax/form.html', message=message)

xhr异步提交

xhr = new XMLHttpRequest()
xhr.open("get", "url", async) // async默认为true,异步提交,否则为同步
xhr.send()

xhr对象拥有readyState属性,该属性值为请求状态:
0(UNSET):未初始化。尚未调用open()方法
1(OPENED):启动。已经调用open()方法,但尚未调用send()方法
2(HEADERS_RECEIVED):发送。已经调用send()方法,且接收到头信息
3(LOADING):接收。已经接收到部分响应主体信息
4(DONE):完成。已经接收到全部內数据,而且已经可以在客户端使用了。

可以在xhr对象的readystatechange事件绑定一个处理方法:

xhr.onreadystatechange = function() {
	if (xhr.readyState === 4 && xhr.status == 200) {
		alert(xhr.responseText);
	}
}

实操:(这部分也是测试用)
Step1:将app.py中的test_form()视图函数修改为以下内容:

@app.route('/form', methods=['GET', 'POST'])
def test_form():
    from time import sleep
    message = None
    if request.method == 'POST':
        pass
        message = '数据处理success'
        return message
    return render_template('ajax/xhr.html', message=message)

step2:新建文件templates/ajax/xhr.html,写入以下内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="message"></div>
<ul id="news"></ul>
<input type="text" name="name" value="">
<select name="newstype" id="newstype">
    <option value="1">新闻</option>
    <option value="2">专题</option>
</select>
<input type="button" name="btn" id="btn" value="提交">
<script>
    btn = document.getElementById('btn')
    message = document.getElementById('message')
    ul = document.getElementById('news')
    // xhr是XMLHttpRequest对象的简称
    // 可以直接在页面内发起请求
    // 从而可以在不刷新页面的情况加载数据
    // 经常加载json格式数据
    // 在js中,json格式数据使用JSON对象进行编解码
    // JSON.parse('["网易", "微专业", "助你成才"]') - 解码
    // JSON.stringify(["网易", "微专业", "助你成才"]) - 编码
    // readyState === 4 请求结束
    // status == 200 请求状态码。 200为正常响应
    // responseText 服务器返回的数据,如果是json字符串格式,可以JSON对象解析
    xhr = new XMLHttpRequest()
    xhr.onreadystatechange = function(ev) {
        console.log(this.readyState)
        console.log(this.status)

        if (this.readyState == 4 && this.status == 200) {
            console.log('服务器返回:', this.responseText)
            message.innerHTML = this.responseText
        }
    }
    btn.onclick = function() {
        // 为xhr创建数据
        message.innerHTML = "请等待..."
        data = new FormData()
        data.append('newstype', document.getElementById('newstype').value)
        // 第一个参数请求方法:get、post
        // get方法,send不用传递数据,通过get的url传送数据
        // post方法,send传递FormData对象数据
        // 第二个参数是请求地址
        // 第三个参数是同步还是异步,默认异步,同步状态下,必须等待响应结果
        // 才能执行下一步js
        xhr.open("post", '{{ url_for("test_form") }}', true)
        xhr.send(data)
    }
</script>
</body>
</html>

页面显示及点击提交的运行结果:
在这里插入图片描述
实操2: 测试从服务器端返回列表或字典数据
Step1:修改app.pytest_form()视图函数,以下内容:

@app.route('/form', methods=['GET', 'POST'])
def test_form():    
    import json
    if request.method == 'POST':
        newstype = request.form['newstype']
        lists = {
            "1": ["新闻1","新闻2","新闻3"],
            "2": ["头条1","头条2","头条3"]
        }
        return json.dumps(lists[newstype])
    return render_template("ajax/xhr.html")

Step2:修改templates/ajax/xhr.html为以下代码:

.
.
.
xhr.onreadystatechange = function(ev) {
   console.log(this.readyState)
    console.log(this.status)

    if (this.readyState == 4 && this.status == 200) {
    	// 修改这里的代码
        data = JSON.parse(this.responseText)
        for(i in data) {
            ul.innerHTML += "<li>" + data[i] + "</li>"
        }
    }
}
.
.
.

分别提交”新闻“和”专题“的运行结果:
在这里插入图片描述

2.3.jQuery的ajax封装

上面用的xhr对象,在IE浏览器中并不能运行。而jQueryajax封装兼容性更好,用起来更方便。

jQuery提供了ajax封装对象。
1.标准的使用方式:

$.ajax({
	type: "POST", // 必写
	url: "http://127.0.0.1/register/", // 必写
	data: data,// 必写
	contentType: ,
	processData: false,
	beforeSend: function() {},
	compplete: function(){},
	success: function(result){},// 必写
	error: function(e){}
});

2.快速使用方式:
dom加载url

$(dom).load(url) // 加载的url内容填充dom节点

get请求

$.get(url, data, callback)

post请求

$.post(url, data, callback)

实操:(这部分也是测试用)
Step1:新建文件templates/ajax/jquery.html,写入以下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static/js/query-3.4.1.min.js"></script>
</head>
<body>
<div id="message"></div>
<ul id="news"></ul>
<input type="text" name="name" value="">
<select name="newstype" id="newstype">
    <option value="1">新闻</option>
    <option value="2">专题</option>
</select>
<input type="button" name="btn" id="btn1" value="ajax提交">
<input type="button" name="btn" id="btn2" value="get提交">
<input type="button" name="btn" id="btn3" value="post提交">
<script>
    btn1 = document.getElementById('btn1')
    btn2 = document.getElementById('btn2')
    btn3 = document.getElementById('btn3')
    message = document.getElementById('message')
    ul = document.getElementById('news')
    // $.ajax参数对象
    // type:请求方式 get、post
    // data:提交数据
    // dataType:返回数据类型 text - 普通文本 json - json格式
    btn1.onclick = function(){
        $.ajax({
            type: 'POST',
            data: {"newstype": "1"}
            dataType: "json",
            success: function(data) {
                for ( i in data) {
                    ul.inneHTML += "<li>" + data[i] + "</li>"
                }
            }
        })
    }
    // 加载一个页面到元素
    {# $('.message').load("/form") #}
    // get方式简写
    btn2.onclick = function(){
        $.get('/form', function(data) {
            $('#message').html(data)
        })
    }
    // post方式简写
    btn3.onclick = function() {
        $.post('/form', {'newstype': '2'}, function(data) {
            for (i in data) {
                ul.innerHTML += "<li>" + data[i] + "</li>"
            }
        }, dataType="json")
    }
</script>
</body>
</html>

实操2: 将发布文章改为ajax异步提交
Step1:修改templates/artilce/post.html中发布文章的的type="button"

.
.
.
<div class="form-group">
	<!-- 这里将原来的submit改为button-->
	<input class="btn" type="button" name="submit" id="btn1" value="发表文章" />
	<input class="btn" type="reset" name="btn2" id="btn2" value="重设" />
</div>
.
.
.

Step2:继续在post.html中添加以下js代码:

<script>
	btn = document.getElementById('btn1')
	btn.onclick = function(ev){
		cate_id = $('#cate').val()
		title = $('#title').val()
		intro = $('#intro').val()
		content = CKEDITOR.instances['content'].getData()

		if (title == '') {
			$('#title').focus()
			return false
		}
		if (intro == '') {
			$('#intro').focus()
			return false
		}
		$.ajax({
			type: 'POST',
			data: {
				'cate': cate_id,
				'title': title,
				'intro': intro,
				'content': content
			},
			dataType: 'json',
			success: function(data) {
				$('#message').html(data.message)
				// 表单重置,相当于点击重设按钮
				// 这里有个坑,下面这一行代码要想生效,上面html代码里的reset按钮中的name和id都不可以等于“reset"
				// 否则会报错$(...)[0].reset() is not a function
				$("form")[0].reset()
				CKEDITOR.instances['content'].setData()
			}
		})
	}
</script>

Step2:替换views/articles.py中的post()视图函数为以下代码:

@article_app.route("/post", methods=['get','post'])
@login_required
def post():
    if request.method == "POST":
        cate_id = request.form['cate']
        title = request.form['title']
        intro    = request.form['intro']
        content  = request.form['content']
        article = Article(
                    cate_id = cate_id,
                    title=title,
                    intro=intro,
                    content=content,
                    author="luxp"
         )

        db.session.add(article)
        db.session.commit()
        # 由于我们是在article_app模块下
        # 因此url_for中的视图函数名可以省略article_app
        import json
        message = {'message': '发布成功'}
        # 因为是异步提交,这里返回的是json数据
        return json.dumps(message)
        # return redirect(url_for(".list"))

    return render_template("article/post.html")
三、课程小结
  • json数据格式
    json串是一种字符串,而不是一种传输方式,传输的方式我们采用的是ajax方式。
  • ajax技术
  • jQueryajax封装

第1章~第6章代码地址: https://pan.baidu.com/s/1FfgbrIw0VwtUDJ-ZVUiAL,提取码:d7ke

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值