我的博客开发(025)

image.png
如图,如果点击修改昵称或者绑定邮箱或者修改密码都可以执行相应操作:
image.png
image.png
首先点击这些按钮应该弹出一个form表单,在user/forms.py中新建一个form:CharngeNicknameFomr类

class ChangeNicknameForm(forms.Form):
    nickname_new = forms.CharField(
        label='新的昵称',
        max_length=20,
        widget=forms.TextInput(
            attrs={'class':'form-control', 'placeholder':'请输入新的昵称'}
        )
    )


    def __init__(self, *args, **kwargs):
        if 'user' in kwargs:
            self.user = kwargs.pop('user')
        super(ChangeNicknameForm, self).__init__(*args, **kwargs)


    def clean(self):
        # 判断用户是否登录
        if self.user.is_authenticated:
            self.cleaned_data['user'] = self.user
        else:
            raise forms.ValidationError('用户尚未登录')
        return self.cleaned_data


    def clean_nickname_new(self):
        nickname_new = self.cleaned_data.get('nickname_new', '').strip()
        if nickname_new == '':
            raise forms.ValidationError("新的昵称不能为空")
        return nickname_new

然后再user/views.py中将上面定义的表单引入,定义新的处理方法:change_nickname:

from .forms import LoginForm, RegForm, ChangeNicknameForm
from .models import Profile

def change_nickname(request):
    redirect_to = request.GET.get('from', reverse('home'))


    if request.method == 'POST':
        form = ChangeNicknameForm(request.POST, user=request.user)
        if form.is_valid():
            nickname_new = form.cleaned_data['nickname_new']
            profile, created = Profile.objects.get_or_create(user=request.user)
            profile.nickname = nickname_new
            profile.save()
            return redirect(redirect_to)
    else:
        form = ChangeNicknameForm()


    context = {}
    context['page_title'] = '修改昵称'
    context['form_title'] = '修改昵称'
    context['submit_text'] = '修改'
    context['form'] = form
    context['return_back_url'] = redirect_to
    return render(request, 'form.html', context)

配置对应的路由:user/rils.py中:
image.png
创建对应的form.html在公用的templates

{% extends 'base.html' %}


{% block title %}{{ page_title }}{% endblock %}
{% block nav_home_active %}active{% endblock %}
{% block content %}
    <div class="containter">
        <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 id="tip" class="text-danger">{{ form.non_field_errors }}</span>
                            <div class="clearfix"></div>
                            <div class="pull-left">
                                {% block other_buttons %}{% endblock %}
                            </div>
                            <div class="pull-right">
                                <input type="submit" value="{{ submit_text }}" class="btn btn-primary">
                                <button class="btn btn-default" onclick="window.location.href='{{ return_back_url }}'">返回</button>
                            </div>
                            
                        </form>
                    </div>
                </div>            
            </div>
        </div>
    </div>    
{% endblock %}

修改usr_Info.html中的昵称:

<li>昵称:{{ user.get_nickname }} <a href="{% url 'change_nickname' %}?from={{ request.get_full_path }}">修改昵称</a></li>

增加返回按钮:在form.html中修改
image.png
然后在user/views.py中将数据传递给前端:
image.png
把两个按钮放在一起:在form.html
image.png
效果:
image.png
另外如果创建的用户没有昵称,user_info.html中的user.profile.nickname就会获取不到内容出错:
image.png
在user/models.py中创建一个get_nickname方法,然后调用该方法赋值给User,如果有直接赋值,没有创建
image.png
在user/modelspy中创建has_nickname方法并赋值给User:
image.png
然后再base.html中将此方法写入:
image.png
对于评论,如果有昵称应该要显示昵称的:
image.png
修改如下:

在user/models.py中的增加get_nicknam_or_username:
image.png
再blog_detail.html中的部分username改为:get_nickname_or_username,同样对于comment/views.py中的username也要修改成get_nickname_or_username:


绑定邮箱:

再user/forms.py中创建BindEmailForm表单用来作为email的表单

class BindEmailForm(forms.Form):
    email = forms.EmailField(
        label='邮箱',
        widget=forms.EmailInput(
            attrs={'class':'form-control', 'placeholder':'请输入正确的邮箱'}
        )
    )
    verification_code = forms.CharField(
        label='验证码',
        required=False,
        widget=forms.TextInput(
            attrs={'class':'form-control', 'placeholder':'点击“发送验证码”发送到邮箱'}
        )
    )


    def __init__(self, *args, **kwargs):
        if 'request' in kwargs:
            self.request = kwargs.pop('request')
        super(BindEmailForm, self).__init__(*args, **kwargs)


    def clean(self):
        # 判断用户是否登录
        if self.request.user.is_authenticated:
            self.cleaned_data['user'] = self.request.user
        else:
            raise forms.ValidationError('用户尚未登录')


        # 判断用户是否已绑定邮箱
        if self.request.user.email != '':
            raise forms.ValidationError('你已经绑定邮箱')


        # 判断验证码
        code = self.request.session.get('bind_email_code', '')
        verification_code = self.cleaned_data.get('verification_code', '')
        if not (code != '' and code == verification_code):
            raise forms.ValidationError('验证码不正确')


        return self.cleaned_data


    def clean_email(self):
        email = self.cleaned_data['email']
        if User.objects.filter(email=email).exists():
            raise forms.ValidationError('该邮箱已经被绑定')
        return email


    def clean_verification_code(self):
        verification_code = self.cleaned_data.get('verification_code', '').strip()
        if verification_code == '':
            raise forms.ValidationError('验证码不能为空')
        return verification_code

在user/views.py中创建bind_email函数:

from django.core.mail import send_mail
from .forms import LoginForm, RegForm, ChangeNicknameForm, BindEmailForm


def bind_email(request):
    redirect_to = request.GET.get('from', reverse('home'))


    if request.method == 'POST':
        form = BindEmailForm(request.POST, request=request)
        if form.is_valid():
            email = form.cleaned_data['email']
            request.user.email = email
            request.user.save()
            return redirect(redirect_to)
    else:
        form = BindEmailForm()


    context = {}
    context['page_title'] = '绑定邮箱'
    context['form_title'] = '绑定邮箱'
    context['submit_text'] = '绑定'
    context['form'] = form
    context['return_back_url'] = redirect_to
    return render(request, 'user/bind_email.html', context)

user/urls.py中增加路由:
image.png
user/user_info.html中增加邮箱内容:
image.png
然后查看效果:
image.png
增加一个发送验证码按钮在新建的bind_email.html,同时修改form.html文件:

新增bind_email.html在user/templates/user中
效果:
image.png
然后增加发送地址并增加样式(在bind_email.html):

同样在user/views.py中增加一个send_verification_code的函数用来发送邮件:

先导入需要的模块:

import string
import random
import time
from django.core.mail import send_mail

image.png
在settings.py中设定email的发送配置
image.png
开启地址:
image.png
配置发送邮件的路由:

user/urls.py:
image.png
尝试发送邮件:
image.png
添加绑定的功能:

上面已经一起实现了

效果图:
image.png
但是现在的发送验证码可以连续不断的发送,这样就会增加服务器的压力,所以需要将按钮变灰,然后功能不可用,并使其开始倒计时:
image.png
在后端同样让发送一封邮件以后关闭端口通知发送邮件(因为可以绕过前端直接操作后端:前端不可信):
image.png
现在绑定邮箱功能还没有实现,还需要继续搞

阅读 187

推荐阅读
我的Django开发
用户专栏

开发一个我的博客网站,一是为了玩,另一方面也是为了助力找工作

2 人关注
31 篇文章
专栏主页