1.選擇好模板,並分析頁面
2.修改並自定義基礎模板
3.修改各個頁面,修改title,麪包屑等
4.定義好用戶信息的View
5. 數據綁定,數據回填
6. 配置路徑利用include
7. 模板顯示,在模板中顯示默認值:{{request.user.mobile|default_if_none:”}}
個人中心頁面配置 (注意debug的使用方法)
製作個人中心基礎模板(usercenter_base),配置基礎快
{% load staticfiles %}
{% block custom_css %}{% endblock %}
{% block header %}{% endblock %}
{% block bread %}{% endblock %}
{% block content_left %}{% endblock %}
{% block content_right %}{% endblock %}
{% block header %}{% endblock %}
{% block custom_js %}{% endblock %}
在基礎模板中完成能複用的代碼塊的數據綁定及配置(block-header)
{% block header %}
<section class="headerwrap headerwrap2">
<header>
<div class="header2 header">
{% if request.user.is_authenticated %}
<div class="top">
<div class="wp">
<div class="fl">
<p>服務電話:<b>33333333</b></p>
</div>
<!--登錄後跳轉-->
<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 }}{{ user.img }}"/></dt>
</dl>
<div class="userdetail">
<dl>
<dt><img width="80" height="80" src="{{ MEDIA_URL }}{{ user.img }}"/></dt>
<dd>
<h2>{{ user.gender }}</h2>
<p>{{ user.username }}</p>
</dd>
</dl>
<div class="btn">
<a class="personcenter fl" href="usercenter_info.html">進入個人中心</a>
<a class="fr" href="{% url 'user_loginout' %}?next={{ request.path }}">退出</a>
<a href="usercenter-message.html">
<div class="msg-num"><span id="MsgNum">0</span></div>
</a>
</div>
</div>
</div>
</div>
</div>
{% else %}
<div class="top">
<div class="wp">
<div class="fl">
<p>服務電話:<b>33333333</b></p></div>
<a style="color:white" class="fr registerbtn" href="{% url 'Register' %}">註冊</a>
<a style="color:white" class="fr loginbtn" href="{% url 'user_login' %}?next={{ request.path }}">登錄</a>
</div>
</div>
{% endif %}
<div class="middle">
<div class="wp">
<a href="index.html"><img class="fl" src="{% static 'images/logo2.png' %}"/></a>
<h1>我的慕學網</h1>
</div>
</div>
</div>
</header>
</section>
{% endblock %}
對用戶中的模板進行數據綁定,主要是custom_right代碼塊
{% block content_right %}
<div class="right">
<div class="personal_des ">
<div class="head" style="border:1px solid #eaeaea;">
<h1>個人信息</h1>
</div>
<div class="inforcon">
<div class="left" style="width:242px;">
<iframe id='frameFile' name='frameFile' style='display: none;'></iframe>
<form class="clearfix" id="jsAvatarForm" enctype="multipart/form-data" autocomplete="off" method="post" action="/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 }}{{ user.img }}">
</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>
<input type='hidden' name='csrfmiddlewaretoken' value='799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' />
</form>
<div style="border-top:1px solid #eaeaea;margin-top:30px;">
<a class="button btn-green btn-w100" id="jsUserResetPwd" style="margin:80px auto;width:100px;">修改密碼</a>
</div>
</div>
<form class="perinform" id="jsEditUserForm" autocomplete="off">
<ul class="right">
<li>暱 稱:
<input type="text" name="nick_name" id="nick_name" value="{{ user.nick_name }}" maxlength="10">
<i class="error-tips"></i>
</li>
<li>生 日:
<input type="text" id="birth_day" name="birday" value="{{ user.birthday }}" readonly="readonly"/>
<i class="error-tips"></i>
</li>
<li>性 別:
<label> <input type="radio" name="gender" value="male" {% if user.gender == 'male' %}checked="checked"{% endif %} >男</label>
<label> <input type="radio" name="gender" value="female" {% if user.gender == 'female' %}checked="checked"{% endif %}>女</label>
</li>
<li class="p_infor_city">地 址:
<input type="text" name="address" id="address" placeholder="請輸入你的地址" value="{{ user.adress }}" maxlength="10">
<i class="error-tips"></i>
</li>
<li>手 機 號:
<input type="text" name="mobile" id="mobile" placeholder="請輸入你的手機號碼" value="{{ user.mobile }}" maxlength="10">
</li>
<li>郵 箱:
<input class="borderno" type="text" name="email" readonly="readonly" value="{{ user.email }}"/>
<span class="green changeemai_btn">[修改]</span>
</li>
<li class="button heibtn">
<input type="button" id="jsEditUserBtn" value="保存">
</li>
</ul>
<input type='hidden' name='csrfmiddlewaretoken' value='799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' />
</form>
</div>
</div>
</div>
{% endblock %}
配置url分發路徑
url(r'^user_center/', include('users.url', namespace='user_info')),# organiztion 的url分發,namespace用於重名的處理
配置實際url路徑
urlpatterns = [
url(r’^user_info/$’, UserInfoView.as_view(), name=’user_info’),
]
配置視圖函數,在後臺進行登陸驗證,未完成登陸則首先獲取來時路徑(request.path),再構造完成login的路徑(綁定來時路徑next_page,格式與前面login函數對應),最後重定向至login頁面,如果已經登陸則渲染正確頁面進行展示
class UserInfoView(View):
def get(self,request):
next_page = request.path #獲取來時路徑
#判斷是否登陸
if not request.user.is_authenticated():
#return render(request,'usercenter_info.html',{})
target_url = '/login/?next='+next_page #拼湊成與login對應的url
return HttpResponseRedirect(target_url) # 轉到來時頁面
if request.user.is_authenticated():
return render(request,'usercenter_info.html',{})
修改個人頭像
1.上傳文件和圖片 ,需要定製一個url,並配置相應的後臺處理視圖函數view對其進行接收處理
2.通用視圖(登陸、權限等)的繼承 10-1
3.定製modelform,進行表單提交
4.視圖函數中實例化form
5.文件上傳會放在了request.FILES
6.前端利用form進行文件的上傳,form表單的提交都需要加上csrf-token,視圖函數利用model_form進行數據轉換
7.image_form.clean_data[‘image’]獲取上傳文件信息,注意字段與前端上傳的name保持一致
8.通過request.user.image=image進行修改信息
9.利用save()進行保存
10.利用HttpResponse進行信息的反饋,提示用戶是否成功
配置url路徑
url(r'^user_img_upload/$', UserImgUploadView.as_view(), name='user_img_upload'),
修改模板,將form的上傳路徑(action)修改爲上傳圖片地址路徑
<form class="clearfix" id="jsAvatarForm" enctype="multipart/form-data" autocomplete="off" method="post" action="{% url 'user_info:user_img_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 }}{{ user.img }}">
</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>
<input type='hidden' name='csrfmiddlewaretoken' value='799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' />
{% csrf_token %}
</form>
創建圖片上傳表單form
class UserImgUploadForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['img']
創建圖片上傳的視圖邏輯,切記上傳圖片用的是post方法,對上傳的方法進行身份認證。文件上傳都是放在request.FILES,所以需要將request.FILES傳入表單中,如果取值正確,則將form中的cleaned_data或files中會有文件信息,將文件信息保存進request.user中,完成圖片更新
class UserImgUploadView(View):
def post(self,request): #上傳是用post方法
next_page = request.path #獲取來時路徑
#判斷是否登陸
if not request.user.is_authenticated():
target_url = '/login/?next='+next_page #拼湊成與login對應的url
return HttpResponseRedirect(target_url) # 轉到來時頁面
if request.user.is_authenticated():
#可以進行圖片上傳工作
img_upload_form = UserImgUploadForm(request.POST,request.FILES)
if img_upload_form.is_valid():
#驗證通過後會將上傳圖片放在cleaned_data內
#image = img_upload_form.cleaned_data['img']
image = img_upload_form.files['image'] #嘗試直接從files裏面取值
#對獲取的圖片進行保存
request.user.img = image
request.user.save()
修改密碼
1.邏輯類似user視圖中的修改密碼
2.利用ajax請求異步修改密碼
3.後臺進行邏輯處理,並利用HttpResponse返回修改信息
4.利用HttpResponse返回json數據,返回錯誤信息 .errors
5.js文件中需要寫入絕對路徑
6., content_type=’application/json’,這個參數別忘了
配置url不要重名,否者不會報錯,但是卻一直錯誤
Ajax的請求只能返回json
配置修改密碼post路徑
#用戶密碼修改
url(r'^password_update/$', UserPasswordUpdateView.as_view(), name='password_update'),
設置視圖函數,完成密碼驗證邏輯.現將密碼上傳至表單,注意name的一致性,判斷表單的正確性,獲取兩個密碼,判斷是否相同,邏輯正確的話進行密碼加密(make_password)保存,邏輯錯誤的話返回錯誤信息
表單驗證
is_valid()合法後的邏輯處理,驗證後的數據保存在實例化後返回的cleaned_data中,cleaned_data是個字典的數據格式,錯誤信息保存在form.errors中比如說想在views中查看所有報錯信息print(f.errors)
class UserPasswordUpdateView(View):
def post(self,request):
password_reset_form = PasswordResetForm(request.POST) #新密碼上傳至表單中
if password_reset_form.is_valid(): #新設置的密碼符合表單的話
password = request.POST.get('password','')
password2 = request.POST.get('password2','')
if password == password2: #兩個密碼相同,所有邏輯正確,進行密碼修改
#在數據庫中信息密碼修改
request.user.password = make_password(password)
request.user.save()
return HttpResponse(json.dumps({'status': 'success'}),content_type='application/json')
else: #如果兩個密碼不相同
return HttpResponse(json.dumps({'status': 'fail','msg':'密碼有誤'}), content_type='application/json') # 將register_form數據傳遞給Template
else: #表單驗證不通過
return HttpResponse(json.dumps({'status': 'fail', 'msg': password_reset_form.errors}),content_type='application/json') # 將register_form數據傳遞給Template
郵箱修改
1.配置驗證碼發送url,用於發送郵箱驗信息及驗證碼的上傳,注意Ajax裏面用的是get還是post方法
2.配置視圖函數,首先先進行登陸判斷,是否是已註冊郵箱的判斷
3.調用以前郵箱發送功能,配置發送email和send_type
4.登陸郵箱獲取驗證碼,填寫完整信息,利用post進行發送
5.查看model是否定義錯誤
接收驗證碼
配置修改郵箱驗證碼發送地址
#接收郵箱驗證碼
url(r'^send_email_code/$', EmailCodeView.as_view(), name='send_email_code'),
配置發送驗證碼邏輯,先對身份進行驗證,然後對已有用戶是否存在相同郵箱進行驗證,成功則存儲郵箱驗證碼信息,並返回Ajax信息(注意get的信息要與html文件中的name一致)
#發送更新郵箱驗證碼
class EmailCodeView(View):
def get(self,request):
#判斷是否登陸,如果未登陸則回到login頁面
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/') # 轉到來時頁面
else:
email = request.GET.get('email','')
# 查詢該郵箱是否已經存在,如果有人已經用了該郵箱則不可以繼續用
whether_exit_email = UserProfile.objects.filter(email=email)
if whether_exit_email:
#告訴用戶該郵箱已經存在
return HttpResponse(json.dumps({'email': '郵箱已經存在'}), content_type='application/json') # 將register_form數據傳遞給Template
else:
#郵箱不存在爲可用郵箱,則發送郵箱驗證碼,並在EmailVerifyCode進行存儲數據
send_email(email, send_type='update') #發送驗證碼
return HttpResponse(json.dumps({'status': 'success'}), content_type='application/json') # 將register_form數據傳遞給Template
修改js文件夾下的js文件,在該路徑下的js文件轉發地址是固定的
//修改個人中心郵箱驗證碼
function sendCodeChangeEmail($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: "get", //注意這裏是用的get方法啦
dataType:'json',
url:"/user_center/send_email_code/",
data:$('#jsChangeEmailForm').serialize(),
async: true,
beforeSend:function(XMLHttpRequest){
$btn.val("發送中...");
$btn.attr('disabled',true);
},
success: function(data){
if(data.email){
Dml.fun.showValidateError($('#jsChangeEmail'), data.email);
}else if(data.status == 'success'){
Dml.fun.showErrorTips($('#jsChangeEmailTips'), "郵箱驗證碼已發送");
}else if(data.status == 'failure'){
Dml.fun.showValidateError($('#jsChangeEmail'), "郵箱驗證碼發送失敗");
}else if(data.status == 'success'){
}
},
complete: function(XMLHttpRequest){
$btn.val("獲取驗證碼");
$btn.removeAttr("disabled");
}
});
}
修改郵箱
配置更新郵箱的信息接收url
#修改個人中心郵箱
url(r'^update_email/$', UpdateEmailView.as_view(), name='update_email'),
完成相應後臺邏輯,注意HttpResponse返回的josn信息不要落下content_type=’application/json’,對身份進行驗證,利用郵箱及驗證碼聯合查詢驗證碼數據庫,進行驗證,成功則進行郵箱修改操作,並返回HttpResponse信息
#郵箱更新view
class UpdateEmailView(View):
def post(self,request):
# 判斷是否登陸,如果未登陸則回到login頁面
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/') # 轉到來時頁面
email = request.POST.get('email', '')
code = request.POST.get('code', '')
# 查詢該郵箱及驗證碼信息
exit_email = EmailVerifyCode.objects.filter(email=email,code=code)
if exit_email: #有該條記錄則驗證正確可以進行修改,完成驗證碼驗證功能,可以進行郵箱修改
request.user.email = email
request.user.save()
return HttpResponse(json.dumps({'status': 'success'}), content_type='application/json')
else:
return HttpResponse(json.dumps({'status': 'fail'}), content_type='application/json')
個人信息修改
配置url
url(r'^user_info/$', UserInfoView.as_view(), name='user_info'),
後臺邏輯
class UserInfoView(View):
def get(self,request):
next_page = request.path #獲取來時路徑
#判斷是否登陸
if not request.user.is_authenticated():
#return render(request,'usercenter_info.html',{})
target_url = '/login/?next='+next_page #拼湊成與login對應的url
return HttpResponseRedirect(target_url) # 轉到來時頁面
if request.user.is_authenticated():
return render(request,'usercenter_info.html',{})
def post(self,request): #注意form表單需要加入csrf-tpken
user_info_form = UserInfodForm(request.POST)
if user_info_form.is_valid():
request.user.nick_name = request.POST.get('nick_name')
request.user.birthday = request.POST.get('birthday')
request.user.gender = request.POST.get('gender')
request.user.adress = request.POST.get('adress')
request.user.mobile = request.POST.get('mobile')
request.user.save()
return HttpResponse(json.dumps({'status': 'success'}),content_type='application/json') # 將register_form數據傳遞給Template
else:
return HttpResponse(json.dumps({'status': 'failure','msg':user_info_form.errors}),content_type='application/json') # 將register_form數據傳遞給Template
html模板form表單完成數據綁定,切記form表單需要csrf-token
<form class="perinform" id="jsEditUserForm" autocomplete="off">
<ul class="right">
<li>暱 稱:
<input type="text" name="nick_name" id="nick_name" value="{{ user.nick_name }}" maxlength="10">
<i class="error-tips"></i>
</li>
<li>生 日:
<input type="text" id="birth_day" name="birthday" value="{{ user.birthday }}" readonly="readonly"/>
<i class="error-tips"></i>
</li>
<li>性 別:
<label> <input type="radio" name="gender" value="male" {% if user.gender == 'male' %}checked="checked"{% endif %} >男</label>
<label> <input type="radio" name="gender" value="female" {% if user.gender == 'female' %}checked="checked"{% endif %}>女</label>
</li>
<li class="p_infor_city">地 址:
<input type="text" name="adress" id="address" placeholder="請輸入你的地址" value="{{ user.adress }}" maxlength="10">
<i class="error-tips"></i>
</li>
<li>手 機 號:
<input type="text" name="mobile" id="mobile" placeholder="請輸入你的手機號碼" value="{{ user.mobile }}" maxlength="10">
</li>
<li>郵 箱:
<input class="borderno" type="text" name="email" readonly="readonly" value="{{ user.email }}"/>
<span class="green changeemai_btn">[修改]</span>
</li>
<li class="button heibtn">
<input type="button" id="jsEditUserBtn" value="保存">
</li>
</ul>
<input type='hidden' name='csrfmiddlewaretoken' value='799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' />
{% csrf_token %}
</form>
js文件完成url地址配置(死地址,以後需要自己修改)
//保存個人資料
$('#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:"/user_center/user_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.birday){
_showValidateError($('#birth_day'), data.birday);
}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");
}
});
});