django用户登录及注册(未使用表单系统)
Web开发 . 2019/11/18发布 . shanyonggang_web . 我要评论 . 258阅读

前言        

博主目前的留言功能直接用的gittalk插件,现在 为实现与用户的评论区互动留言,因此在自己的网站内增加用户登录注册功能,目前只有可以登录的用户才可以进行文章的评论互动,一步步来,后续会引入第三方登录。

新建APP

首先新建一个用户信息的APP,在settings.py里添加新建的APP,怎么创建大家应该都清楚。

创建用户model

此处根据自己需要保存用户的信息字段需求创建模型(后续也可以根据业务需要随时添加修改),新创建的模型是在django自带的User模型基础之上新添加额外的字段,具体可以参考扩展User类,博主的模型如下:

from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserProfile(AbstractUser):
    # 创建时间
    c_time = models.DateTimeField(auto_now_add=True)
    # 电话号码字段
    phone = models.CharField(max_length=20, blank=True)
    # 头像
    avatar = models.ImageField(upload_to='avatar/%Y%m%d/', blank=True)
    # 个人网站
    your_url = models.URLField(verbose_name='个人网站', blank=True)
    # 微信号
    wechat = models.CharField(max_length=20, blank=True)
    # QQ号
    QQ_num = models.CharField(max_length=20, blank=True)
    # 昵称
    nickname = models.CharField(max_length=20, blank=True)

    class Meta:
        ordering = ['c_time']
        verbose_name = '用户'
        verbose_name_plural = '用户'

配置urls.py

        此处比较简单,直接给出代码,如下:

from django.urls import path
from . import views

app_name = 'userprofile'

urlpatterns = [
    # 用户登录
    path('login/', views.user_login, name='login'),
    # 用户登出
    path('logout/', views.user_logout, name='logout'),
    # 用户注册
    path('register/', views.user_register_no_form, name='register'),
    # 用户更新(更新除了头像的信息)
    path('update/', views.user_update, name='update'),
    # 用户修改个人头像信息 (暂时保存)
    path('user_info/', views.user_info, name='user_info'),
]

编写前端模版

        博主采用的是模态框形式(bootstrap模态框),通过点击登录或者注册按钮,跳出相应的弹框,进行用户的注册及登录,同时前后端数据通过ajax进行请求,接下来分块给出具体代码,其中点击按钮的代码如下:

         <ul class="nav navbar-nav navbar-right">
            {% if user.is_authenticated %}
              <!-- 如果用户已经登录,则显示用户名下拉框 -->
              <li class="dropdown">
                  {% if user.nickname %}
                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ user.nickname }}<span class="caret"></span></a>
                  {% else %}
                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ user.username }}<span class="caret"></span></a>
                  {% endif %}
                  <ul class="dropdown-menu">
                    <li><a href="#">系统消息</a></li>
                    <li role="separator" class="divider"></li>
                    <li><a href="{% url 'user_profile:update' %}">个人信息</a></li>
                    <li role="separator" class="divider"></li>
                    <li><a href="{% url 'user_profile:logout' %}">退出登录</a></li>
                  </ul>
              </li>
            <!-- 如果用户未登录,则显示 “登录” -->
            {% else %}
              <button type="button" class="btn btn-primary btn-lg user_register" data-toggle="modal" data-target="#myModal">
                  注册
              </button>
              <button type="button" class="btn btn-primary btn-lg user_login" data-toggle="modal" data-target="#myModal">
                  登录
              </button>
            <!-- if 语句在这里结束 -->
            {% endif %}
        </ul>

        用户登录成功,显示系统消息、个人信息、退出登录,未登录则显示注册和登录两个按钮,接下来给出弹框的代码,如下:

<!-- 用户登录框 -->
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="title">用户登录</h4>
      </div>
      <div class="modal-body">
        <div></div>
      </div>
    </div>
  </div>
</div>

<!-- 用户登录div设计 -->
<div style="display: none;" id="add_html">
  <div class="container-fluid" id="change_login">
      <div class="row">
          <div class="col-8">
              <form class="form-group" method="post" action="#" id="login_form" enctype="multipart/form-data">
                  {% csrf_token %}
                  <div class="form-group">
                      <label for="username">用户名</label>
                      <input class="form-control" type="text" id="username" name="username" placeholder="">
                  </div>
                  <div class="form-group">
                      <label for="password">密码</label>
                      <input class="form-control" type="password" id="password" name="password" placeholder="">
                  </div>
                  <div style="margin-right: auto;margin-left: auto;background-color:silver,saddlebrown;width:150px;text-align: center">
                      <b id="login-fail" style="color: red"></b>
                  </div>
                  <div class="text-right">
                      <button class="btn btn-primary" type="button" onclick="login_submit()">登录</button>
                      <button class="btn btn-danger" data-dismiss="modal">取消</button>
                  </div>
                  <a href="" onclick="chang_user_register_click()" data-toggle="modal" data-target="#register">还没有账号?点我注册</a>               
                </form>
          </div>
      </div>
  </div>
  <!-- 用户注册div设计 -->
  <div id="change_register">
    <form class="form-group" method="post" action=""enctype="multipart/form-data">
      {% csrf_token %}
          <div class="form-group">
              <label for="username_re">用户名</label>
              <input class="form-control" type="text" id="username_re" name="username_re"  placeholder="6-15位字母或数字" required>
          </div>
          <div class="form-group">
              <label for="password1">密码</label>
              <input class="form-control" type="password" id="password1" name="password1" placeholder="至少6位字母或数字" required>
          </div>
          <div class="form-group">
              <label for="password2">再次输入密码</label>
              <input class="form-control" type="password" id="password2" name="password2" placeholder="至少6位字母或数字" required>
          </div>
          <div class="form-group">
              <label for="email">邮箱</label>
              <input class="form-control" type="email" id="email" name="email"  placeholder="例如:123@123.com">
          </div>
          <div style="margin-right: auto;margin-left: auto;background-color:silver,saddlebrown;width:150px;text-align: center">
            <b id="register-fail" style="color: red"></b>
          </div>
          <div class="text-right">
              <button class="btn btn-primary" type="button" onclick="register_sbumit()">提交</button>
              <button class="btn btn-danger" data-dismiss="modal">取消</button>
          </div>
          <a href="" onclick="chang_user_login_click()" data-toggle="modal" data-target="#login">已有账号?点我登录</a>
    </form>
  </div>
</div>

        解析一下,这块主要提供了三块,一个是基础框,一个是登录框、一个是注册框,博主是通过js实现点击已有帐号?点我登录和还没帐号?点我注册实现登录信息和注册信息在模态框中的基础框内的表切换,具体的js代码如下:

// 用户登录注册加载
// 登录
$('.user_login').click(
    function(){
    var login_html = $('#add_html #change_login').prop("outerHTML");
    $('#title').text('用户登录');
    $('.modal-body div').remove();
    $('.modal-body').append(login_html);
    });

// 注册
$('.user_register').click(
    function(){
        var register_html = $('#add_html #change_register').prop("outerHTML");
        $('#title').text('用户注册');
        $('.modal-body div').remove();
        $('.modal-body').append(register_html);
    });
// 注册页面切换到登录页面
function chang_user_login_click(){
    var login_html = $('#add_html #change_login').prop("outerHTML");
    $('#title').text('用户登录');
    $('.modal-body div').remove();
    $('.modal-body').append(login_html);
    $('#login-fail').html('');
}
// 登录页面切换到注册页面
function chang_user_register_click(){
    var register_html = $('#add_html #change_register').prop("outerHTML");
    $('#title').text('用户注册');
    $('.modal-body div').remove();
    $('.modal-body').append(register_html);
    $('#register-fail').html('');
}
// 用户登录的ajax请求
function login_submit(){
$.ajax({
    cache:false,
    type:"POST",
    url:"/userprofile/login/",
    dataType:'json',
    data:{
        "username":$("#username").val(),
        "password":$("#password").val(),
        // "password2":$("#password2").val(),
        // "email":$("#email").val(),
        "csrfmiddlewaretoken":$('[name="csrfmiddlewaretoken"]').val()
    },
    //通过id找到提交form表单,并将表单转成字符串
    async:true,
    //异步为真,ajax提交的过程中,同时可以做其他的操作
    success:function (data) {
        //jquery3以后,会将回传过来的字符串格式的data自动json解析不用再使用一遍JSON.parse(data)了,不然反而会在控制台报错
        if(data.status=="success"){
            window.location.href = "/";
        }else if(data.status=="fail"){
            $('#login-fail').html(data.msg);
        }
    }
    });
}
//如果显示了错误信息,修改输入框内容,错误信息隐藏
$("input").bind('input propertychange', function() {
    $('#login-fail').html('');
});
// 用户注册的请求
function register_sbumit(){
    $.ajax({
        cache:false,
        type:"POST",
        url:"/userprofile/register/",
        dataType:'json',
        data:{
            "username":$("#username_re").val(),
            "password":$("#password1").val(),
            "password2":$("#password2").val(),
            "email":$("#email").val(),
            "csrfmiddlewaretoken":$('[name="csrfmiddlewaretoken"]').val()
        },
        //通过id找到提交form表单,并将表单转成字符串
        async:true,
        //异步为真,ajax提交的过程中,同时可以做其他的操作
        success:function (data) {
            //jquery3以后,会将回传过来的字符串格式的data自动json解析不用再使用一遍JSON.parse(data)了,不然反而会在控制台报错
            if(data.status == "success"){
                window.location.href = "/";
            }else if(data.status == "fail"){
                $('#register-fail').html(data.msg);
            }
        }
    });
    }
//如果显示了错误信息,修改输入框内容,错误信息隐藏
$("input").bind('input propertychange', function() {
    $('#register-fail').html('');
});

        其中,这段js代码里也包含了与后台数据交互的代码,具体也比较简单,想了解django中的ajax请求的直接百度即可,接下来我们就要编写后台验证的视图模版代码了

编写views.py

        此处博主尝试用了form表单来实现前后台交互,但是中间出现了比较多的bug,因此改用了直接在views.py里验证存储的方式,具体的views.py代码如下:

from django.shortcuts import render, redirect, HttpResponseRedirect, HttpResponse
from django.contrib.auth import authenticate, login, logout
from django.contrib import auth
from django.http import JsonResponse
from django.urls import reverse
from . import forms
from user_profile.models import UserProfile
from django.views.decorators.csrf import csrf_exempt
import re
from django.db.models import Q
from django.contrib.auth.hashers import make_password, check_password  # 密码加密
from .models import UserProfile
import json


# Create your views here.

# 用户注册
# 验证邮箱
def email_check(email):
    pattern = re.compile(r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?")
    return re.match(pattern, email)


# 用户登录
@csrf_exempt
def user_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        pwd = request.POST.get('password')
        username_or_not = UserProfile.objects.filter(username=username)
        print(username_or_not)
        if username_or_not:
            username_or_not = UserProfile.objects.get(username=username)
            print(username_or_not.password)
            if not check_password(pwd, username_or_not.password):
                print('验证密码')
                return HttpResponse('{"status":"fail","msg":"您输入的密码有误!"}')
        else:
            print('验证用户')
            return HttpResponse('{"status":"fail","msg":"用户名不存在!"}')
        print(pwd)
        user = auth.authenticate(username=username, password=pwd)
        if user is not None and user.is_active:
            print('login success')
            # 登录成功
            auth.login(request, user)
            return HttpResponse('{"status":"success"}')


# 用户退出
def user_logout(request):
    logout(request)
    return redirect("index:blog_list")


# 用户注册(没有用表单验证)
@csrf_exempt
def user_register_no_form(request):
    if request.method == 'POST':
        email = request.POST.get('email')
        password = password1 = request.POST.get('password')
        password2 = request.POST.get('password2')
        username = request.POST.get("username")
        print(username, email, password1, password2)
        # 验证username
        filter_result = UserProfile.objects.filter(username=username)
        if username:
            if len(filter_result) > 0:
                #  表示用户已经存在
                return HttpResponse('{"status":"fail","msg":"该用户名已存在"}')
        else:
            # 表示用户未输入用户名
            return HttpResponse('{"status":"fail","msg":"请输入一个用户名"}')
        # 验证email
        filter_result = UserProfile.objects.filter(email=email)
        if email_check(email):
            if len(filter_result) > 0:
                #  表示该邮箱已经注册
                return HttpResponse('{"status":"fail","msg":"该邮箱已经注册"}')
        else:
            # 表示用户未输入邮箱
            return HttpResponse('{"status":"fail","msg":"请输入一个正确的邮箱"}')
        # 验证密码
        if len(password1) < 6:
            return HttpResponse('{"status":"fail","msg":"请输入一个至少6位数的密码"}')  # 表示密码少于6位
        elif len(password1) > 15:
            return HttpResponse('{"status":"fail","msg":"请输入一个最多15位数的密码"}')  # 表示密码多于15位
        # 验证密码是否一致
        if password1 and password2 and password1 != password2:
            return HttpResponse('{"status":"fail","msg":"请查看两次密码是否输入一致"}')
        # 验证完成,保存数据
        password1 = make_password(password1)
        UserProfile.objects.create(username=username, password=password1, email=email)
        print('Save Success!')
        print(password1)
        user = auth.authenticate(username=username, password=password)
        auth.login(request, user)
        return HttpResponse('{"status":"success"}')



#  用户信息更新
@csrf_exempt
def user_update(request):
    # return HttpResponse("进入用户编辑页面")
    if request.method == 'POST':
        nickname = request.POST.get('nickname')
        phone = request.POST.get('phone')
        your_url = request.POST.get('user_url')
        email = request.POST.get('email')
        wechat = request.POST.get('wechat')
        qq = request.POST.get('qq')
        image = request.FILES.get('images')
        if request.user:
            user_info = UserProfile.objects.get(username=request.user)
            if nickname:
                user_info.nickname = nickname
            if phone:
                user_info.phone = phone
            if your_url:
                user_info.your_url = your_url
            if email:
                user_info.email = email
            if qq:
                user_info.QQ_num = qq
            if wechat:
                user_info.wechat = qq
            if image:
                user_info.avatar = image
            user_info.save()
            return redirect('/userprofile/update/')
        return redirect('/userprofile/update/')
    return render(request, 'userprofile/userinfo.html')

        此处就比较简单的,看代码即可看懂,可能中间验证逻辑会有些许bug,但是暂时没发现,如果您在注册或登录过程中遇到bug的,请在下面留言指出!感谢您的建议!至此就可以实现用户的注册和登录,看到这了不如注册个帐号测试下去吧!注:博主服务器承受能力有限(阿里云最便宜的),切勿随意乱进行注册登录,谢谢理解!!!


  • 有疑问请在下方评论区留言,我会尽快回复。
  • Email私信我: 511248513@qq.com 或添加博主 微信
本文作者:shanyonggang_web
发布时间:2019年11月18日 14:43
许可协议: 署名-非商业性使用 4.0 国际许可协议
知识共享许可协议     转载请保留原文链接及作者
正在加载今日诗词....
您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请狠狠点击下面的


登录 后回复

当前暂无评论,点击登录来做第一个吃螃蟹的人吧!