使用Django搭建博客第二天笔记--登录注册功能实现

一、数据表结构设计
项目应用account的模型MyUser是项目中的核心数据,它与每个项目应用的模型都存在数据关联。模型MyUser继承内置模型User,在内置模型User的基础上添加新的字段,用于完善用户信息。打开项目应用account的models.py定义模型MyUser,代码如下:

class MyUser(AbstractUser):
    name = models.CharField(verbose_name="姓名",max_length=50,default='匿名用户')
    introduce = models.TextField(verbose_name='简介',default="暂无介绍")
    company = models.CharField(verbose_name="公司",max_length=100,default='暂无信息')
    profession = models.CharField(verbose_name='职业',max_length=100,default='暂无信息')
    address = models.CharField(verbose_name='地址', max_length=100, default='暂无信息')
    telephone = models.CharField(verbose_name='电话', max_length=11, default='暂无信息')
    wx = models.CharField(verbose_name='微信', max_length=50, default='暂无信息')
    qq = models.CharField(verbose_name='qq',max_length=50,default='暂无信息')
    wb = models.CharField(verbose_name='微博', max_length=100, default='暂无信息')
    photo = models.ImageField(verbose_name='头像', blank=True,upload_to='images/user/')
    create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)

    class Meta:
        verbose_name = '用户'
        verbose_name_plural = verbose_name
        db_table = 'MyUser'

    def __str__(self):
        return self.name

二、路由定义
采用路由下发的方式,我们在Myblog的urls.py下设置account的路由

#  Myblog的 urls.py
urlpatterns = [
    path('admin/', admin.site.urls),
    path('user/', include('app.account.urls')),
]
# account的 urls.py
urlpatterns = [
    path('register', Register.as_view(), name="register"),
    path('login', UserLogin.as_view(), name="userLogin"),
]

三、编写视图类
我们在account创建一个一个forms.py用来创建UserForm类,用来进行表单认证:

from django import forms
from django.forms import Form
from app.account.models import MyUser
from captcha.fields import CaptchaField

class UserForm(Form):
    username = forms.CharField(
        widget=forms.TextInput
    )
    password = forms.CharField(
        widget=forms.PasswordInput
    )
    cp = forms.CharField(
        widget=forms.PasswordInput,
        required=False
    )
    type = forms.CharField(
        widget=forms.TextInput
    )
    captcha = CaptchaField()

    def clean(self):
        username = self.cleaned_data.get("username", '')

        if self.cleaned_data.get("type", '') == 'register':
            if not username:
                raise forms.ValidationError("用户名不能为空")
            else:
                user = MyUser.objects.filter(username=username).exists()
                if user:
                    raise forms.ValidationError("用户名已存在")

            p = self.cleaned_data.get("password", '')
            cp = self.cleaned_data.get("cp", '')

            if p != cp:
                raise forms.ValidationError("两次密码不一致")

            else:
                d = {
                    'username': username,
                    'password': p,
                    'is_superuser': 1,
                    'is_staff': 1
                }
                user = MyUser.objects.create_user(**d)# create_user自动将明文密码hash加密
                user.save()
        else:
            if not username:
                raise forms.ValidationError("用户名不能为空")

在account的view.py添加如下代码

from django.shortcuts import render, redirect, reverse
from django.views.generic import View
from .forms import *
from django.contrib.auth import authenticate, login
from captcha.models import CaptchaStore
from captcha.helpers import captcha_image_url


class Register(View):
    info = {
        'title': '注册博客',
        'pageTitle': '用户注册',
        "confirmPassword": True,
        'button': '注册',
        "urlText": '用户登录',
        "submitUrl": 'register',
        "urlName": 'userLogin',
        "tips": '',
        'form': '',
    }

    def get(self, request):
        self.info['form'] = UserForm()
        return render(request, 'user.html', self.info)

    def post(self, request):
        user_from = UserForm(request.POST)

        if user_from.is_valid():
            self.info["tips"] = '注册成功,请登录'
            return redirect(reverse("register"), self.info)
        else:
            self.info["tips"] = user_from.errors.as_data().values()
            return render(request, 'user.html', self.info)


class UserLogin(View):
    info = {
        'title': '登录博客',
        'pageTitle': '用户登录',
        'button': '登录',
        'urlText': '用户注册',
        'urlName': 'register',
        'submitUrl': 'userLogin',
        'tips': '',
        'form': '',
        'new_key': '',
        'image_url': ''
    }

    def get(self, request):
        self.info['new_key'] = CaptchaStore.pick()  # 生成hashkey
        self.info['image_url'] = captcha_image_url(self.info['new_key'])  # 生成验证码图片url地址

        self.info['form'] = UserForm()
        return render(request, 'user.html', self.info)

    def post(self, request):
        user_from = UserForm(request.POST)

        # 表单验证
        if user_from.is_valid():

            username = user_from.cleaned_data.get("username", '')
            password = user_from.cleaned_data.get("password", '')

            if not username or not password:
                self.info['tips'] = "用户名或密码不能为空"
                return render(request, 'user.html', self.info)

            else:
                if MyUser.objects.filter(username=username).exists():
                    user = authenticate(username=username, password=password)
                    if user:
                        if user.is_active:
                            '''
                            
                            '''
                            login(request, user)
                            return redirect(reverse("index"), self.info)
                    else:
                        self.info['tips'] = '密码错误'
                        return render(request, 'user.html', self.info)
                else:
                    self.info['tips'] = '用戶不存在'
                    return render(request, 'user.html', self.info)
        else:
            self.info["tips"] = user_from.errors.as_data().values()
            return render(request, 'user.html', locals())

四、jinja2模板引擎
更换django自带的模板引擎,采用jinja2模板引擎,在Myblog的setting中,在TEMPLATES配置中设置jinja2,用Myblog创建jinja2.py添加jinja2环境

# Myblog的setting中
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'environment': 'Myblog.jinja2.environment',
        },
    },
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
#  jinja2.py
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from jinja2 import Environment


# 将jinja2 模板设置到项目环境中
def environment(**options):
    env = Environment(**options)
    env.globals.update({
        'static': staticfiles_storage.url,
        'url': reverse,
    })
    return env

五、模板编写
jinja2模板引擎编写,跟django自带的模板用法类似

<!DOCTYPE html>
<html lang="en">
<head>
	<title>{
   
   { title }}</title>
	<link rel="stylesheet" href="{
   
   {static('css/reset.css')}}">
	<link rel="stylesheet" href="{
   
   {static('css/user.css')}}">
    <script src="{
   
   {static('js/jquery.min.js')}}"></script>
    <script src="{
   
   {static('js/user.js')}}"></script>
</head>
<body>
<div class="page">
	<div class="loginwarrp">
		<div class="logo">{
   
   { pageTitle }}</div>
        <div class="login_form">
			<form name="Login" method="post" action="{
   
   { url(submitUrl) }}">
                {#  解决跨越访问#}
                <input type="hidden" name="csrfmiddlewaretoken" value="{
   
   { csrf_token }}">
                <input type="hidden" name="type" value="{
   
   { submitUrl }}">

				<li class="login-item">
					<span>用户名:</span>
					<input type="text" name="username" class="login_input" >
                    <span id="count-msg" class="error"></span>
				</li>
				<li class="login-item">
					<span>密 码:</span>
					<input type="password" name="password" class="login_input">
                    <span id="password-msg" class="error"></span>
				</li>
                {% if confirmPassword %}
                    <li class="login-item">
                        <span>确认密码:</span>
                        <input type="password" name="cp" class="login_input">
                        <span id="password-msg" class="error"></span>
				    </li>
                {% endif %}
                <li class="login-item">
					<span>验证码:</span>
                    <input type="text" class='login_input' id="id_captcha_1" name="captcha_1" placeholder='验证码' placeholder-data="验证码" />
                    <input type="hidden" id="id_captcha_0" name="captcha_0" value="{
   
   { new_key }}"> <img src="{
   
   { image_url }}" alt="captcha" class="captcha"> <br>
                    <span id="password-msg" class="error"></span>
				</li>

                <div>{
   
   { tips }}</div>
				<li class="login-sub">
					<input type="submit" name="Submit" value="{
   
   { button }}">
                    <div class="turn-url">
                        <a style="color: #45B572;" href="{
   
   { url(urlName) }}">>>{
   
   { urlText }}</a>
                    </div>
				</li>				
           </form>
		</div>
	</div>
</div>
<script type="text/javascript">
	window.onload = function() {
		var config = {
			vx : 4,
			vy : 4,
			height : 2,
			width : 2,
			count : 100,
			color : "121, 162, 185",
			stroke : "100, 200, 180",
			dist : 6000,
			e_dist : 20000,
			max_conn : 10
		}
		CanvasParticle(config);
	}
</script>

<script>
//点击验证码刷新
$(function () {
    $('.captcha').click(function () {
        console.log("click");
        $.getJSON("/captcha/refresh", function (result) {
            $(".captcha").attr('src', result['image_url']);
            $('#id_captcha_0').val(result['key'])
        });});
});
</script>

<script src="{
   
   { static('js/canvas-particle.js') }}"></script>
</body>
</html>

六、验证码

七、效果图
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45723275/article/details/120518500