32、修改用户信息
1、修改用户信息
1、昵称
2、邮箱
3、密码
2、修改昵称
- 注意:
- user不定有对应的Profile的(未创建)
- 昵称不能为空(Form表单判断)
在“个人资料”这里,我们要实现点击“修改昵称”弹出一个form表单出来,这里有多种方式可以实现,可以弹出一个小窗口,也可以用ajax提交的形式,但这些写的代码会有点多。这里我们采用一种方法:打开一个form表单,我们把这个form表单做的比较通用。因为我们发现之前的user里面登录和注册的html代码写的差不多
那现在我们要给一个form表单 填新的昵称,在user/forms.py里新建一个修改昵称的form
# 修改昵称的表单
class ChangeNicknameForm(forms.Form):
nickname_new = forms.CharField(
label='新的昵称',
max_length=20,
widget=forms.TextInput(
attrs={'class':'form-control', 'placeholder': '请输入新的昵称'}
)
)
有了这个form表单,我们还需要有一个具体的处理方法去把它给渲染出来,打开user/views.py
from .forms import ChangeNicknameForm
from .models import Profile
def change_nickname(request):
if request.method == 'POST':
pass
else:
form = ChangeNicknameForm()
context = {}
context['form'] = form
return render(request, '', context)
对应的,我们要配置下路由,修改user/urls.py如下:
这里,我们还差一个模板页面,我们不打算新建一个模板页面,而是建一个通用的表单 form.html。在全局的templates下新建form.html(复制user/templates/user/login.html代码,稍做修改),写入如下代码:
<!-- C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\templates\form.html -->
{% extends 'base.html' %}
{% block title %}
{{ page_title }}
{% endblock %}
{% block nav_home_active %}active{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-xs-4 col-xs-offset-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{form_title}}</h3>
</div>
<div class="panel-body">
<form action="" method="POST">
{% csrf_token %}
{% for field in form %}
{% if not field.is_hidden %}
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% endif %}
{{ field }}
<p class="text-danger">{{ field.errors.as_text }}</p>
{% endfor %}
<span class="pull-left text-danger">{{ form.non_field_errors }}</span>
<input type="submit" value="{{ submit_text}}" class="btn btn-primary pull-right">
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
然后完善补全user/views.py里面的change_nickname内容(即对应上面html里面的字段:page_title、form_title、submit_text、form):
然后把user/templates/user/user_info.html里面“修改昵称”对应的url链接填上
重启服务
接下来我们把点击“修改”按钮对应POST的方法编写一下,在user/views.py里,这里我们需要判断两个东西:提交的新昵称是否为空、是否登录了。我们可以回到forms.py进行修改:
修改forms.py如下:
修改views.py如下:
然后修改user_info.html,进行显示修改之后的昵称:
刷新页面
这里有几个地方的细节我们还没有处理好
(1)from参数需要加上去。修改user_info.html:
(2)表单提交最好加上一个“返回”按钮。修改form.html:
然后在forms.py里面加入return_back_url这个字段
(3)如果一开始用户没有昵称的时候,是没有对应的profile的,那么在user_info.html里面直接由profile获取昵称就会有问题,所以这里最好做一个判断,判断它是否有profile,如果有的话,我们就显示nickname,如果没有profile的话,就不显示。
有一种方法是直接在这里写模板标签,但直接判断不太好写。自然而然我们想到用自定义模板标签,但这里用的话,也会比较复杂。这里我们考虑用一种新的方法,根据python的语言特性,对这个进行动态绑定。这个user对象一定是存在的,对它绑定一个方法,直接获取nickname,在这个方法里面我们就可以做判断了,判断是否有profile。我们试着在models.py中进行动态绑定
修改models.py如下:
修改user_info.html如下:
另外一个问题,导航栏处和评论处,最好也显示昵称
(1)导航栏显示昵称。需要修改base.html:
我们先在models.py中添加一个判断是否有昵称的方法,动态绑定到User这个模型,修改如下:
修改base.html如下:
(2)评论显示昵称。
在models中多加一个方法,获取昵称或者用户名。修改models.py如下:
修改blog_detail.html如下:
还有一个位置要改。因为评论是异步提交,它返回的数据是通过comment/views.py返回,这里返回的是文本,这里也需要改一下username,注意,这里get_nickname_or_username后面需要加上括号,因为这里用的是方法,而刚刚的模板页面里方法是不需要加括号的,直接返回就可以
刷新页面
至此,我们昵称修改就没有问题了
3、绑定邮箱
- 需要验证邮箱
- 发送邮件验证
如果我们没有绑定,那么就出现“绑定邮箱”给它绑定。如果已经绑定了,那么就出现“解绑”或者“不解绑”都可以,我们先不考虑解绑情况,先默认“不解绑”。
绑定邮箱这里我们肯定要填一个邮箱地址,那怎么判断填写的邮箱地址是否正确呢?最好的方法就是给这个邮箱发送一封邮件,这就涉及到django怎么发送邮件。另外一个,发送邮件怎么确保这个信息是正确的然后给绑定呢?有两种方法,一种是发送一条链接,点击链接实现绑定功能,这个方法有点复杂,我们用另外一种方法,发送一个验证码到邮箱,然后把验证码填到绑定邮箱的表单位置,表单就会有邮箱和验证码两个信息,就可以实现绑定了。
这里要创建一个form表单,表单要填写两个信息:邮箱、验证码。修改user/forms.py如下:
然后需要对应的views处理表单(参考修改昵称的change_nickname代码),修改user/views.py如下:
然后写路由。修改user/urls.py如下:
然后模板页面。填写上user/templates/user/user_info.html里面绑定邮箱这一部分:
写完以后,刷新页面
然后表单里验证码这一字段,我们需要添加上“发送验证码”这个按钮。这里我们可以继承这个通用的页面,再加上一个其他按钮就可以,修改templates/form.html如下(其中的clearfix是对页面清除浮动):
那么其他按钮可以会执行一些代码,这些额外代码我们可以写到base.html另外一个block块block script_extends里面去实现,在base.html,form.html是继承base.html的,所以也继承了它的块的信息。
接下来我们继承下这个页面,给他绑定邮箱。在user/templates/user/下新建bind_email.html(填写上user/views.py里bind_email方法里面最后一行的render的链接为“‘user/bind_email.html’”),这个bind_email.hrml继承form.html这个表单,需要单独编写的内容就是上面的other_buttons这个块。bind_email.html写入如下代码:
刷新页面
这里先实现一个功能,点击“发送验证码”这个按钮,实现发送验证码到邮箱。继续修改bind_email.html:
刷新页面,当输入邮箱为空时点击“发送验证码”
那如果有邮箱,就需要发送邮件到这个邮箱,发送邮件在前端页面是发送不了的,我们后端需要提供一个链接,让它调用。那我们简单的用GET请求传一个邮箱地址进去,传进去之后就利用这个邮箱发送邮件,这里我们就在后端页面定义一个方法。修改views.py如下:
发送邮件我们要引用一个东西,可以查看django官方文档:
文档1(https://docs.djangoproject.com/en/2.0/ref/settings/#email)
文档2(https://docs.djangoproject.com/en/2.0/topics/email/)
另外再说一个重点位置,我们发送邮件会有一些相关的配置,可以查看文档:(https://docs.djangoproject.com/en/2.0/ref/settings/#email)
修改mysite/settings.py修改如下:
那现在要说一下怎么去开启qq邮箱的SMTP这个服务,然后怎么去获取授权码。
打开qq邮箱并登陆。点开“设置”——“账户”——开启服务“POP3/SMTP”——点击“生成授权码”——打开手机QQ或者QQ安全中心扫二维码(一旦你改了QQ邮箱密码,就需要更改一下授权码)
接着, 我们处理方法还没有配置链接,修改urls.py如下:
写完之后这个方法就可以调用了(调用这个方法,最好是用异步提交)。我们回到bind_email.html修改如下:
那我们发送邮件相关的方法写好以后,我们刷新页面,输入邮箱,点击“发送验证码”。然后登陆邮箱就能收到一封邮件,复制验证码,填入绑定邮箱表单的验证码处
然后点击“绑定”,这里会有一些东西需要处理,
第一个,验证码处出现“请填写字段”的提示,我们最好改一改,让它不是必填。
在user/forms.py中,verification_code字段里面加一条required=False,
,设置为False的话,我们就需要做一些验证了,手动验证验证码是否为空,
修改user/forms.py如下:
第二个,我们需要验证邮箱是否已经存在了,存在就不能继续被绑定。修改user/forms.py如下:
第三点,我们还要判断一个东西,绑定邮箱这个用户是否已经登录,而且是否已经绑定邮箱这些信息。那么这里我们最好把request.user传进来,但这里还要考虑到一个东西,还要验证其验证码是否正确,那么这里就可以考虑直接把request传进来进行处理(参考上面修改昵称表单ChangeNicknameForm里面的判断用户是否登录那段代码),修改user/forms.py如下:
验证大概就这么多。
下一步,我们要实现绑定的功能,完善views.py里的bind_email如下:
刷新页面,测试
还有个小细节需要处理
我们先进入后台管理,将邮箱删掉,保存,然后回到绑定邮箱这个表单。
如果我们不断点“发送验证码”不断发送邮件,这个是不行的,会增加服务器压力的,那我们这里最好要加一点限制。
首先前端页面bind_email.html,发送验证码的过程中,一旦发送过了,就不让它再发送了
刷新页面
但是秉着前端不可信原则,人们总是能够绕过前端页面,直接调用发送邮件的接口,那我们不能总让他们一直调用接口,因此我们后端要做一个限制,在views.py中send_verification_code方法中,最好能保存一下之前什么时候发送过邮件,在限制的时间间隔内不让它继续发送邮件就可以。修改views.py如下
4、修改密码
(放在下一节讲)
- 登录的情况,修改密码
- 未登录的情况,忘记密码