django编写个人博客(十七)修改用户信息

1、修改用户昵称

创建一个form.html页面,如下

{%extends 'base.html'%}


{%block title%}
{{page_title}}
{%endblock%}


{%block nav_home_active%}
active
{%endblock%}
{%block content%}
<div class="cotainer">
    <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="pull-left 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>
</div>

{% endblock %}

修改user下对应的表单

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

    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

对应views下的方法,传回所需参数

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)

把博客页面对应位置改为昵称,没有昵称显示用户名

这里采用动态绑定方法

from django.db import models
from django.contrib.auth.models import User


# Create your models here.
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    nickname = models.CharField(max_length=20, verbose_name='昵称')

    def __str__(self):
        return '<Profile: %s for %s>' % (self.nickname, self.user.username)


def get_nickname(self):
    if Profile.objects.filter(user=self).exists():
        profile = Profile.objects.get(user=self)
        return profile.nickname
    else:
        return ''


def get_nickname_or_username(self):
    if Profile.objects.filter(user=self).exists():
        profile = Profile.objects.get(user=self)
        return profile.nickname
    else:
        return self.username


def has_nickname(self):
    return Profile.objects.filter(user=self).exists()


User.get_nickname = get_nickname
User.has_nickname = has_nickname
User.get_nickname_or_username=get_nickname_or_username

路由:

 path('change_nickname/',views.change_nickname,name='change_nickname'),

 

对应blogdetail页面

{% extends 'base.html' %}
{#页面标题#}
{% block title %}
<h3>{{blog.title}}</h3>
{% endblock %}
{% load static %}
{%load comment_tags%}
{%block head_extend%}
     <link rel="stylesheet" href="/static/blog/blog.css">
     <script type="text/javascript" src="{% static 'ckeditor/ckeditor-init.js' %}"></script>
<script type="text/javascript" src="{% static 'ckeditor/ckeditor/ckeditor.js' %}"></script>
<script src="{% static 'ckeditor/ckeditor/plugins/prism/lib/prism/prism_patched.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'prism/prism.css' %}">
{% endblock %}

{%block nav_blog_active%}
active
{%endblock%}
  {%block content%}

<div class="container">

    <div class="row">
        <div class="col-xs-10 col-xs-offset-1">
            <div class="panel panel-default">
  <div class="panel-body">
    <h3>{{blog.title}}</h3>
            <ul class="blog_info_description">
<li>作者:{{blog.author}}</li>
            <li>
    分类:<a href="{%url 'blogs_with_type' blog.blog_type.pk%}">
    {{blog.blog_type}}</a>
</li>
<li>发表日期:{{blog.created_time|date:"Y-m-d H:i:s"}}</li>
                <li>阅读:({{blog.get_read_num}})</li>
                <li>评论({%get_comment_count blog%})</li>

            </ul>
      <hr>
<div class="blog_content">{{blog.content|safe}}</div>
      <hr>
<div class="blog_more">
    <p>上一篇
        {%if previous_blog %}
        <a href="{% url 'blog_detail' previous_blog.pk %}">{{previous_blog.title}}</a>
       {%else%}
        没有了
        {%endif%}
    </p>

   <p>下一篇
        {%if next_blog %}
        <a href="{% url 'blog_detail' next_blog.pk %}">{{next_blog.title}}</a>
       {%else%}
        没有了
        {%endif%}
    </p>
</div>
        </div>
    </div>
  </div>
</div>

     <div class="row">
        <div class="col-xs-10 col-xs-offset-1">

            <div class="panel panel-default">
  <div class="panel-body">
    <div class="comment-area">

                <h3 class="comment-area-title">提交评论区域</h3>
             {%if user.is_authenticated %}

                <form  id="comment_form" action="{%url 'update_comment' %}" method="POST" style="overflow:hidden">
                    {%csrf_token%}
                     <label for="comment-text">{{user.get_nickname_or_username}},欢迎评论</label>
                      <div id="reply_content_container" style="display:none;">
                                <p id="reply_title">回复:</p>
                                <div id="reply_content"></div>
                            </div>
                    {%get_comment_form blog%}
                    <span id="comment_error" class="text-danger pull-left"></span>
                    <input type="submit" class="btn btn-primary pull-right" value="评论" >
                </form>


             {%else%}
             您尚未登录登录后方可评论

                <a class="btn btn-primary" href="{%url 'login'%}?from={{ request.get_full_path }}">登录</a>
                <span>or</span>
                <a class="btn btn-danger" href="{%url 'register'%}?from={{ request.get_full_path }}">注册</a>

             {%endif%}

         </div>
        <div class="comment-area2">
                    <h3 class="comment-area-title">评论列表</h3>
                    <div id="comment_list">
                        {%get_comment_list blog as comments%}

                        {% for comment in comments %}
                            <div id="root_{{ comment.pk }}" class="comment">
                                <span>{{ comment.user.get_nickname_or_username}}</span>
                                <span>({{ comment.comment_time|date:"Y-m-d H:i:s" }}):</span>
                                <div id="comment_{{ comment.pk }}">
                                    {{ comment.text|safe }}
                                </div>
                                <a href="javascript:reply({{ comment.pk }});">回复</a>


                                {% for reply in comment.root_comment.all %}
                                    <div class="reply">
                                        <span>{{ reply.user.get_nickname_or_username }}</span>
                                        <span>({{ reply.comment_time|date:"Y-m-d H:i:s" }})</span>
                                        <span>回复</span>
                                        <span>{{ reply.reply_to.get_nickname_or_username }}:</span>
                                        <div id="comment_{{ reply.pk }}">
                                            {{ reply.text|safe }}
                                        </div>
                                        <a href="javascript:reply({{ reply.pk }});">回复</a>
                                    </div>
                                {% endfor %}
                            </div>
                        {% empty %}
                            <span id="no_comment">暂无评论</span>
                        {% endfor %}
                    </div>
                </div>
  </div>
</div>

            </div>
        </div>
    </div>
div>
{% endblock %}

{%block script_extends %}
<script type="text/javascript">
function reply(reply_comment_id)
{
 $('#reply_comment_id').val(reply_comment_id);
 var html=$("#comment_"+reply_comment_id).html();
 $('#reply_content').html(html);
 $('#reply_content_container').show();
 $('html').animate({scrollTop: $('#comment_form').offset().top - 60}, 300, function(){
                CKEDITOR.instances['id_text'].focus();
            });
}
   function numFormat(num){
            return ('00' + num).substr(-2);
        }
        function timeFormat(timestamp){
            var datetime = new Date(timestamp * 1000);
            var year = datetime.getFullYear();
            var month = numFormat(datetime.getMonth() + 1);
            var day = numFormat(datetime.getDate());
            var hour = numFormat(datetime.getHours());
            var minute = numFormat(datetime.getMinutes());
            var second = numFormat(datetime.getSeconds());
            return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
        }
     $("#comment_form").submit(function(){
            // 判断是否为空
            $("#comment_error").text('');
            if(CKEDITOR.instances["id_text"].document.getBody().getText().trim()==''){
                $("#comment_error").text('评论内容不能为空');
                return false;
            }
            // 更新数据到textarea
            CKEDITOR.instances['id_text'].updateElement();
            // 异步提交
            $.ajax({
                url: "{% url 'update_comment' %}",
                type: 'POST',
                data: $(this).serialize(),
                cache: false,
                success: function(data){
                    console.log(data);
                    if(data['status']=="SUCCESS"){
                            if($('#reply_comment_id').val()=='0')
                          {

                            var comment_html = '<div id="root_' + data['pk'] + '" class="comment"><span>' + data['username'] + '</span><span> (' + timeFormat(data['comment_time']) + '):</span><div id="comment_' + data['pk'] + '">' + data['text'] + '</div><a href="javascript:reply(' + data['pk'] + ');">回复</a></div>';
                             $("#comment_list").prepend(comment_html);
                             }
                             else
                             {  var reply_html ='<div class="reply"><span>' + data['username'] + '</span><span> (' + timeFormat(data['comment_time']) + ')</span><span> 回复 </span><span>' + data['reply_to'] + ':</span><div id="comment_' + data['pk'] + '">' + data['text'] + '</div><a href="javascript:reply(' + data['pk'] + ');">回复</a></div>';
                            $("#root_" + data['root_pk']).append(reply_html);
                             }

                        CKEDITOR.instances['id_text'].setData('');
                         $('#reply_content_container').hide();
                         $('reply_comment_id').val('0');
                        $('#no_comment').remove();
                        $('#comment_error').text('评论成功');
                    }else{
                        // 显示错误信息
                        $("#comment_error").text(data['message']);
                    }
                },
                error: function(xhr){
                    console.log(xhr);
                }
            });
            return false;
        });


</script>
{%endblock%}

效果显示:

 2、绑定邮箱

对应form表单

class BindEmailForm(forms.Form):
    email = forms.EmailField(label='邮箱',

                             widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': '请输入正确邮箱'}))
    verify_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 __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', '')
        verify_code = self.cleaned_data.get('verify_code', '')
        print(code,verify_code)
        if not (code != '' and code == verify_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):
        verify_code = self.cleaned_data.get('verify_code', '').strip()
        if verify_code == '':
            raise forms.ValidationError('验证码不能为空')
        return verify_code

对应views 发送验证码方法,其中将生成验证码放在session中和输入的对比

def send_verify_code(request):
    email = request.GET.get('email', '')

    data = {}

    if email != '':
        # 生成验证码
        code = ''.join(random.sample(string.ascii_letters + string.digits, 4))

        request.session['bind_email_code'] = code 


            # 发送邮件
        send_mail(
                '绑定邮箱',
                '验证码:%s' % code,
                '3374399586@qq.com',
                [email],
                fail_silently=False,
            )
        data['status'] = 'SUCCESS'
    else:
        data['status'] = 'ERROR'
    return JsonResponse(data)

settings邮箱对应配置

# https://docs.djangoproject.com/en/2.0/ref/settings/#email
# https://docs.djangoproject.com/en/2.0/topics/email/
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.qq.com'
EMAIL_PORT = 25
EMAIL_HOST_USER = '3374399586@qq.com'
EMAIL_HOST_PASSWORD = 'akndabykjedrdacf'  # 授权码
EMAIL_SUBJECT_PREFIX = '[管伟鸿的博客] '
EMAIL_USE_TLS = True  # 与SMTP服务器通信时,是否启动TLS链接(安全链接)

邮箱异步提交方法,这里新建了一个html页面,继承了forms.html

{%extends 'form.html' %}
{%block other_buttons %}
<button id="send_code" class="btn btn-primary">发送验证码</button>
{%endblock%}
{%block script_extends %}
<script type="text/javascript">
      $("#send_code").click(function(){
            var email = $("#id_email").val();
            if(email==""){
                $("#tip").text('* 邮箱不能为空');
                return false;
            }
            // 发送验证码
            $.ajax({
                url: "{% url 'send_verify_code' %}",
                type: "GET",
                data: {
                    'email': email
                },
                cache: false,
                success: function(data){
                    if(data['status']=='ERROR'){
                        alert(data['status']);
                    }
                }
            });
             return false;
});
</script>
{%endblock%}

绑定邮箱的方法,这里传入的是request

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)

相应路由

效果:

使按钮变灰

在模板页面添加

 $(this).addClass('disabled');
            $(this).attr('disabled', true);
            var time = 30;
            $(this).text(time + 's');
            var interval = setInterval(() => {
                if(time <= 0){
                    clearInterval(interval);
                    $(this).removeClass('disabled');
                    $(this).attr('disabled', false);
                    $(this).text('发送验证码');
                    return false;
                }
                time --;
                $(this).text(time + 's');
            }, 1000);


             return false;
});

 在后台进行对应验证

def send_verify_code(request):
    email = request.GET.get('email', '')

    data = {}

    if email != '':
        # 生成验证码
        code = ''.join(random.sample(string.ascii_letters + string.digits, 4))

        request.session['bind_email_code'] = code
        now=int(time.time())
        send_code_time=request.session.get('send_code_time',0)
        if now-send_code_time<30:
            data['staus']='ERROR'

        else:    # 发送邮件
            request.session['send_code_time'] = now
            request.session['bind_email_code'] = code

            send_mail(
                    '绑定邮箱',
                    '验证码:%s' % code,
                    '3374399586@qq.com',
                    [email],
                    fail_silently=False,
                )
            data['status'] = 'SUCCESS'
    else:
        data['status'] = 'ERROR'
    return JsonResponse(data)

3、利用邮箱进行登录

修改forms的对应表单

class LoginForm(forms.Form):
    username_or_email = forms.CharField(label='用户名或邮箱',
                                        widget=forms.TextInput(
                                            attrs={'class': 'form-control', 'placeholder': '请输入用户名或邮箱'}))
    password = forms.CharField(label='密码',
                               widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入密码'}))

    def clean(self):
        username_or_email = self.cleaned_data['username_or_email']
        password = self.cleaned_data['password']
        user = auth.authenticate(username=username_or_email, password=password)
        if user is None:  # 登录
            if User.objects.filter(email=username_or_email).exists():
                username = User.objects.get(email=username_or_email).username
                user = auth.authenticate(username=username, password=password)
                if not user is None:
                    self.cleaned_data['user'] = user
                    return self.cleaned_data
            raise (forms.ValidationError('用户名或密码错误'))
        else:
            self.cleaned_data['user'] = user
        return self.cleaned_data

4、修改密码

对应的form

class ChangePasswordForm(forms.Form):
    old_password = forms.CharField(label='旧的密码',
                                   widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入旧密码'}))
    new_password = forms.CharField(label='新的密码',
                                   widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入新密码'}))
    new_password_again = forms.CharField(label='新的密码',
                                         widget=forms.PasswordInput(
                                             attrs={'class': 'form-control', 'placeholder': '请再次输入新密码'}))

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

    def clean(self):
        new_password = self.cleaned_data.get('new_password', '')
        new_password_again = self.cleaned_data.get('new_password_again', '')
        if new_password != new_password_again or new_password == '':
            raise forms.ValidationError('两次输入的密码不一致')
        return self.cleaned_data

    def clean_old_password(self):
        old_password = self.cleaned_data.get('old_password', '')
        if not self.user.check_password(old_password):
            raise forms.ValidationError('旧的密码错误')
        return old_password
def change_password(request):
    redirect_to = reverse('home')
    if request.method == 'POST':
        form = ChangePasswordForm(request.POST, user=request.user)
        if form.is_valid():
            user = request.user
            # old_password=form.cleaned_data['old_password']
            new_password = form.cleaned_data['new_password']
            user.set_password(new_password)
            user.save()
            auth.logout(request)
            return redirect(redirect_to)


    else:
        form = ChangePasswordForm()
    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)

对应路由

5、忘记密码,通过邮箱进行验证

对应的表单

class ForgotPasswordForm(forms.Form):
    email = forms.EmailField(label='邮箱',

                             widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': '请输入正确邮箱'}))
    verify_code = forms.CharField(label='验证码',
                                  required=False,
                                  widget=forms.TextInput(
                                      attrs={'class': 'form-control', 'placeholder': '点击"发送验证码"发送到邮箱'}))
    new_password = forms.CharField(label='新的密码',
                                   widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入新密码'}))

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

    def clan_email(self):
        email= self.cleaned_data['email'].strip()
        if not User.objects.filter(email=email).exists():
            raise forms.ValidationError('邮箱不存在')
        return email

    def clean_verify_code(self):
        verify_code = self.cleaned_data.get('verify_code', '').strip()
        if verify_code == '':
            raise forms.ValidationError('验证码不能为空')
        code = self.request.session.get('forgot_password_code', '')
        verify_code = self.cleaned_data.get('verify_code', '')

        if not (code != '' and code == verify_code):
            raise forms.ValidationError('验证码不正确')
        return verify_code

 对应的views方法

def forgot_password(request):
    redirect_to = reverse('login')
    if request.method == 'POST':
        form = ForgotPasswordForm(request.POST, request=request)
        if form.is_valid():
            email = form.cleaned_data['email']
            new_password = form.cleaned_data['new_password']
            user = User.objects.get(email=email)
            user.set_password(new_password)
            user.save()
            # 清除session
            del request.session['forgot_password_code']
            return redirect(redirect_to)
    else:
        form = ForgotPasswordForm()

    context = {}
    context['page_title'] = '重置密码'
    context['form_title'] = '重置密码'
    context['submit_text'] = '重置'
    context['form'] = form
    context['return_back_url'] = redirect_to
    return render(request, 'user/forgot_password.html', context)

对应路由

对应的页面

{%extends 'form.html' %}
{%block other_buttons %}
<button id="send_code" class="btn btn-primary">发送验证码</button>
{%endblock%}
{%block script_extends %}
<script type="text/javascript">
      $("#send_code").click(function(){
            var email = $("#id_email").val();
            if(email==""){
                $("#tip").text('* 邮箱不能为空');
                return false;
            }
            // 发送验证码
            $.ajax({
                url: "{% url 'send_verify_code' %}",
                type: "GET",
                data: {
                    'email': email,
                     'send_for': 'forgot_password_code'
                },
                cache: false,
                success: function(data){
                    if(data['status']=='ERROR'){
                        alert(data['status']);
                    }
                }
            });
            $(this).addClass('disabled');
            $(this).attr('disabled', true);
            var time = 30;
            $(this).text(time + 's');
            var interval = setInterval(() => {
                if(time <= 0){
                    clearInterval(interval);
                    $(this).removeClass('disabled');
                    $(this).attr('disabled', false);
                    $(this).text('发送验证码');
                    return false;
                }
                time --;
                $(this).text(time + 's');
            }, 1000);


             return false;
});
</script>
{%endblock%}

 入口在user_info中

同时可以加入下拉表中

效果

 

 

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值