mxonline实战14,全局搜索,修改个人中心页面个人资料信息
对应github地址:第14天
一. 全局搜索
1. 使用关键词搜索
courses/views.py/CourseListView新增代码,不用把search_keywords传到前端
同样在organization/views.py/OrgView,拷贝上面代码,做简单修改
organization/views.py/TeacherListView添加
2. 搜索的js代码放在deco-common.js中
//顶部搜索栏搜索方法
function search_click(){
var type = $('#jsSelectOption').attr('data-value'),
keywords = $('#search_keywords').val(),
request_url = '';
if(keywords == ""){
return
}
keywords = encodeURIComponent(keywords)
if(type == "course"){
request_url = "/course/list?keywords="+keywords
}else if(type == "teacher"){
request_url = "/org/teacher/list?keywords="+keywords
}else if(type == "org"){
request_url = "/org/list?keywords="+keywords
}
window.location.href = request_url
}
注意: 如果关键词是中文或者特殊字符需要加这行转换格式: keywords = encodeURIComponent(keywords)
二. 个人中心页面
1. 把usercenter开头的6个页面拷贝到templates目录,分析发现这几个页面头部和左边内容都是一样的,只有右边内容不同。
2. 建立个人中心base页面
新建文件usercenter-base.html;把usercenter-info.html的内容拷贝到usercenter-base.html中,把几个页面不同的地方加上block模板标签:基本包括标题,js和css,面包屑;页面右边的部分也可以定义一个block模板标签;
替换静态文件地址:需要{% load staticfiles %}
3. 编写usercenter-info.html,
3.1 继承usercenter-base.html页面,注意extends 继承页面的时候要用引号把基础页面引用起来
3.2 编写URL, VIEW
users/views.py中添加
users/models.py中添加
4. 填充页面信息
图像,昵称
性别
邮箱有一个readonly字段,表明不能改变
手机号:如果后台没写手机号,会自动显示为None,如果想显示为空可加上default_if_none参数
5. 修改用户中心头像
参考organization/form.py中定义的一个ModelForm
1)在users/forms.py中定义
2)users/views.py中
3)user/urls.py添加
4)usercenter-info.html中关于修改图形的代码如下
<form class="clearfix" id="jsAvatarForm" enctype="multipart/form-data" autocomplete="off" method="post" action="{% url 'users:image_upload' %}" target='frameFile'>
<label class="changearea" for="avatarUp">
<span id="avatardiv" class="pic">
<img width="100" height="100" class="js-img-show" id="avatarShow" src="{{ MEDIA_URL }}{{ request.user.image }}"/>
</span>
<span class="fl upload-inp-box" style="margin-left:70px;">
<span class="button btn-green btn-w100" id="jsAvatarBtn">修改头像</span>
<input type="file" name="image" id="avatarUp" class="js-img-up"/>
</span>
</label>
{% csrf_token %}
</form>
注意:
enctype="multipart/form-data" 这个字段必须加上,才能把文件类型传递给后台
action="{% url 'users:image_upload' %}" 添加数据上传地址
<input type="file" name="image" id="avatarUp" class="js-img-up"/> 其中的属性name值必须是"image",它和forms.py中取出的fields值是对应的
6. 修改密码
6.1 user/views.py编写UpdatePwdView视图,和class ModifyPwdView(View)类似
6.2 users/urls.py添加
6.3 修改usercenter-base.html中的修改密码的表单
这里name属性的值需要和form表单中定义的值相同,因为我们是视图类中使用了modify_form = ModifyPwdForm(request.POST)
相应的js代码是在deco-user.js中
$(function(){
//个人资料修改密码
$('#jsUserResetPwd').on('click', function(){
Dml.fun.showDialog('#jsResetDialog', '#jsResetPwdTips');
});
$('#jsResetPwdBtn').click(function(){
$.ajax({
cache: false,
type: "POST",
dataType:'json',
url:"/users/update/pwd/",
data:$('#jsResetPwdForm').serialize(),
async: true,
success: function(data) {
if(data.password1){
Dml.fun.showValidateError($("#pwd"), data.password1);
}else if(data.password2){
Dml.fun.showValidateError($("#repwd"), data.password2);
}else if(data.status == "success"){
Dml.fun.showTipsDialog({
title:'提交成功',
h2:'修改密码成功,请重新登录!',
});
Dml.fun.winReload();
}else if(data.msg){
Dml.fun.showValidateError($("#pwd"), data.msg);
Dml.fun.showValidateError($("#repwd"), data.msg);
}
}
});
});
注意:
1). 代码中 url:"/users/update/pwd/" js文件中不能使用模板标签,只能按照urls.py中定义的路径来写
2). 代码中data:$('jsResetPwdForm').serialize(),通过序列化表单值,创建URL编码文本字符串,把序列化的值传给ajax()作为url的参数,轻松使用ajax()提交form表单,可参考https://www.cnblogs.com/leejersey/p/3750259.html
7. 在base.html增加用户登录验证显示功能,也就是修改全局头部
<!--登录后跳转-->
{% if request.user.is_authenticated %}
<div class="personal">
<dl class="user fr">
<dd> {{ user.username }} <img class="down fr" src="/static/images/top_down.png"/></dd>
<dt><img width="20" height="20" src="{{ MEDIA_URL }}{{ request.user.image }}"/></dt>
</dl>
<div class="userdetail">
<dl>
<dt><img width="80" height="80" src="{{ MEDIA_URL }}{{ request.user.image }}"/></dt>
<dd>
<h2>{{ request.user.nick_name }}</h2>
<p>{{ request.user.username }}</p>
</dd>
</dl>
<div class="btn">
<a class="personcenter fl" href="{% url 'users:info' %}">进入个人中心</a>
<a class="fr" href="/logout/">退出</a>
</div>
</div>
</div>
{% else %}
<div class="wp">
<div class="fl"><p>服务电话:<b>33333333</b></p></div>
<a style="color:white" class="fr registerbtn" href="{% url "users:register" %}">注册</a>
<a style="color:white" class="fr loginbtn" href="/login/">登录</a>
</div>
{% endif %}
在usercenter-base.html和org_base.html页面的相应位置粘贴相同代码
8. 发送邮箱验证码
通过向用户邮箱中发送一个验证码的方法来修改邮箱地址
8.1 users/models.py->EmailVerifyRecord中添加一个选择类型
8.2 apps/utils/email_send.py添加发送邮件功能
上面这种写法指定验证码为4位,功能其实是无效的,因为在前面定义中code为16位并且保存找到了数据库。这样设置只会在邮箱中收到4位验证码,但是实际保存到数据库中的还是16位验证码,在页面中也要输入16位验证码
如果想指定4位,需要加一个判断条件,如下
8.3 修改url 和view
users/usls.py中添加
users/views.py中添加
说明:如果是新邮箱,就执行send_register_email函数,执行这个函数就会把新邮箱保存在数据库中
8.4 相应的js功能在deco-user.js中
//个人资料邮箱修改
function changeEmailSubmit($btn){
var verify = verifyDialogSubmit(
[
{id: '#jsChangeEmail', tips: Dml.Msg.epMail, errorTips: Dml.Msg.erMail, regName: 'email', require: true},
]
);
if(!verify){
return;
}
$.ajax({
cache: false,
type: 'post',
dataType:'json',
url:"/users/send_email_code/ ",
data:$('#jsChangeEmailForm').serialize(),
async: true,
beforeSend:function(XMLHttpRequest){
$btn.val("发送中...");
$btn.attr('disabled',true);
$("#jsChangeEmailTips").html("验证中...").show(500);
},
success: function(data) {
if(data.email){
Dml.fun.showValidateError($('#jsChangeEmail'), data.email);
}else if(data.status == "success"){
Dml.fun.showErrorTips($('#jsChangePhoneTips'), "邮箱信息更新成功");
setTimeout(function(){location.reload();},1000);
}else{
Dml.fun.showValidateError($('#jsChangeEmail'), "邮箱信息更新失败");
}
},
complete: function(XMLHttpRequest){
$btn.val("完成");
$btn.removeAttr("disabled");
}
});
}
注意
1. url:"/users/send_email_code/ " 要和urls.py中的地址一样
2. data:$('#jsChangeEmailForm').serialize()中记得在id=jsChangeEmailForm的表单中中添加{% csrf_token %},是在usercenter-base.html中,然后就可以把{% csrf_token %}带到后端
9. 修改用户邮箱
9.1 修改url, view
users/urls.py添加
users/views.py添加
说明:执行修改邮箱之前会先验证邮箱是否为新邮箱,而在验证邮箱的过程中已经把新email存放在数据库中
9.2 相关js代码,保存在deco-user.js
//个人资料邮箱修改
function changeEmailSubmit($btn){
var verify = verifyDialogSubmit(
[
{id: '#jsChangeEmail', tips: Dml.Msg.epMail, errorTips: Dml.Msg.erMail, regName: 'email', require: true},
]
);
if(!verify){
return;
}
$.ajax({
cache: false,
type: 'post',
dataType:'json',
url:"/users/update_email/ ",
data:$('#jsChangeEmailForm').serialize(),
async: true,
beforeSend:function(XMLHttpRequest){
$btn.val("发送中...");
$btn.attr('disabled',true);
$("#jsChangeEmailTips").html("验证中...").show(500);
},
success: function(data) {
if(data.email){
Dml.fun.showValidateError($('#jsChangeEmail'), data.email);
}else if(data.status == "success"){
Dml.fun.showErrorTips($('#jsChangePhoneTips'), "邮箱信息更新成功");
setTimeout(function(){location.reload();},1000);
}else{
Dml.fun.showValidateError($('#jsChangeEmail'), "邮箱信息更新失败");
}
},
complete: function(XMLHttpRequest){
$btn.val("完成");
$btn.removeAttr("disabled");
}
});
}
10. 个人中心其他信息表单的提交
信息包含昵称,生日,性别,地址,电话;这些信息已经在UserProfile的model中定义过,因此这里可以使用ModelForm
10.1 users/forms.py中新增
10.2 之前我们定义了个人中心静态页面显示的View的get方法,可以再定义一个post方法,用于提交数据
其中return HttpResponse里的{"status": "success"}和下面js代码中的 else if(data.status == "success")是相对应的
10.3 相应js代码同样保存在deco-user.js中
//保存个人资料
$('#jsEditUserBtn').on('click', function(){
var _self = $(this),
$jsEditUserForm = $('#jsEditUserForm')
verify = verifySubmit(
[
{id: '#nick_name', tips: Dml.Msg.epNickName, require: true}
]
);
if(!verify){
return;
}
$.ajax({
cache: false,
type: 'post',
dataType:'json',
url:"/users/info/",
data:$jsEditUserForm.serialize(),
async: true,
beforeSend:function(XMLHttpRequest){
_self.val("保存中...");
_self.attr('disabled',true);
},
success: function(data) {
if(data.nick_name){
_showValidateError($('#nick_name'), data.nick_name);
}else if(data.birthday){
_showValidateError($('#birth_day'), data.birthday);
}else if(data.address){
_showValidateError($('#address'), data.address);
}else if(data.status == "failure"){
Dml.fun.showTipsDialog({
title: '保存失败',
h2: data.msg
});
}else if(data.status == "success"){
Dml.fun.showTipsDialog({
title: '保存成功',
h2: '个人信息修改成功!'
});
setTimeout(function(){window.location.href = window.location.href;},1500);
}
},
complete: function(XMLHttpRequest){
_self.val("保存");
_self.removeAttr("disabled");
}
});
});
});
在usercenter-info.html中添加csrf_token
注意:
1. 之前我们定义用户生日的时候,数据类型是DateField;而我们在前端修改生日时,由前端传到后台的其实是字符串,而Django会自动把字符串转换为DateField类型,debug中查看cleaned_date字段类似如下
努力生活,融于自然