django搭建博客七用户注册

2022年05月22日 未雨晴空 0评论 3948阅读 1喜欢

页面模板

新建\myblog\templates\user\register.html

{% extends 'base.html' %}
{% load static %}
{% block title %}注册{% endblock %}
{% block main %}
    <div class="container">
        <form class="form-signin bg-white" method="post" action="{% url 'system:register' %}" id="register-form">
            <div class="text-center mb-4">
                <img class="mb-2" src="{% static '/images/favicon.png' %}" alt="" width="100" height="100">
                <h1 class="h3 mb-3 font-weight-normal">欢迎注册本博客</h1>
                <div class="rollContainer">
                    <p class="rollBlock">友情提示:请使用QQ邮箱完成站点注册,谢谢!</p>
                </div>
                <div class="login_error">
                    {% for k,v in register_form.errors.items %}
                        {{ v }}
                    {% endfor %}
                </div>
            </div>

            <div class="form-label-group">
                <input type="text" id="inputUsername" name="username"
                       value="{% if register_form.username.value %}{{ register_form.username.value }}{% endif %}"
                       class="form-control {% if register_form.errors.username %}is-invalid{% endif %}"
                       placeholder="用户名" aria-describedby="usernameHelpBlock" required autofocus>
                <label for="inputEmail">用户名</label>
                <small id="usernameHelpBlock" class="form-text text-muted">
                    用户名只能包括中文,字母,数字,长度限制在2—15位
                </small>
            </div>

            <div class="form-label-group">
                <input type="email" id="inputEmail" name="email"
                       value="{% if register_form.email.value %}{{ register_form.email.value }}{% endif %}"
                       class="form-control {% if register_form.errors.email %}is-invalid{% endif %}" placeholder="邮箱"
                       aria-describedby="emailHelpBlock" required>
                <label for="inputEmail">邮箱</label>
                <small id="emailHelpBlock" class="form-text text-muted">
                    请输入你的邮箱
                </small>
            </div>

            <div class="form-label-group">
                <input type="password" id="inputPassword" name="password"
                       value="{% if register_form.password.value %}{{ register_form.password.value }}{% endif %}"
                       class="form-control {% if register_form.errors.password %}is-invalid{% endif %}" placeholder="密码"
                       aria-describedby="passwordHelpBlock" required>
                <label for="inputPassword">密码</label>
                <small id="passwordHelpBlock" class="form-text text-muted">
                    密码必须在6-18之间,允许包括字母,数字以及<span style="font-size: small;font-weight: bold">.@+-_?&%$</span>>这些字符组合
                </small>

            </div>

            <div class="form-label-group">
                <input type="password" id="inputPassword" name="repassword"
                       value="{% if register_form.repassword.value %}{{ register_form.repassword.value }}{% endif %}"
                       class="form-control {% if register_form.errors.repassword %}is-invalid{% endif %}"
                       placeholder="重复密码" aria-describedby="repasswordHelpBlock" required>
                <label for="inputPassword">重复密码</label>
            </div>

            <div class="form-label-group">
                {{ register_form.captcha }}
            </div>

            <small class="form-text text-muted my-3">
                注册完毕,激活邮件将会发送到您的邮箱,还望查收。
            </small>
            <button class="btn btn-lg btn-success btn-block" type="submit">注册</button>
            {% csrf_token %}
        </form>
        <div class="clearfix " style="width: 100%;max-width: 420px;padding: 15px;margin: auto;">
            <p class="float-left"><a class="text-muted " href="#">←回到首页</a></p>
            <p class="float-right">
                <a class="text-muted " href="#">登录</a>
                |
                <a class="text-muted " href="#">忘记密码</a>
            </p>
        </div>
    </div>
{% endblock %}

页面效果:
在这里插入图片描述

注册激活邮件

编辑\myblog\system\tools.py

内容如下,RegisterActiveEmailSender继承之前封装的EmailSender,重写了get_template_context函数,实现了注册激活需要的参数逻辑。

from django.urls import reverse
from django.utils.crypto import get_random_string
from system.models import EmailRecord, User
from django.core.mail import send_mail
from django.template.loader import render_to_string
from myblog.email_settings import EMAIL_FROM
from myblog.settings import SITE_URL, SITE_NAME
import logging

logger = logging.getLogger(__name__)

...

"""
注册激活邮件发送器
"""

class RegisterActiveEmailSender(EmailSender):
    template_name = "user/email-register-active.html"

    def get_template_context(self, password=""):
        context = super(RegisterActiveEmailSender, self).get_template_context()
        self.record.url = self.site_url + reverse(viewname='sys:register_active', kwargs={'code': self.record.code})
        context.update({"url": self.record.url, "password": password})
        return context

注册激活邮件任务

新增\myblog\system\tasks.py

添加以下内容,需要注意这里文件名必须为tasks.py,便于后面celery的自动任务发现机制。可以看到下面发送邮件是区分了两种环境的。

如果是DEBUG=False(生产环境)的情况下则是交给celery异步发送邮件,同时在之前prod_settings.py里面已经配置过 EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"

而在DEBUG=True(开发环境)则是同步发送且因为在dev_settings.py里面定义了

EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" ,邮件直接输出在控制台,便于开发调试。

from celery import shared_task
from django.conf import settings
from system.models import EmailType
from system.tools import RegisterActiveEmailSender
import logging

logger = logging.getLogger("django")


@shared_task
def _send_email(email_type=None, username=None, *args, **kwargs):
    if email_type == EmailType.ACTIVE:
        RegisterActiveEmailSender(EmailType.ACTIVE, username).send(*args, **kwargs)
    else:
        pass


def send_email(email_type=None, username=None, *args, **kwargs):
    if settings.DEBUG:
        _send_email(email_type, username, *args, **kwargs)
    else:
        _send_email.delay(email_type, username, *args, **kwargs)

注册表单

编写\myblog\system\forms.py

添加以下内容,需要注意这里面使用到了django-simple-captcha依赖,如下面的

from captcha.fields import CaptchaField,这个在之前初始化工程的时候已经安装了开发环境下需要的依赖了。

import logging
from captcha.fields import CaptchaField
from django import forms
from django.core import validators
from system.models import User

logger = logging.getLogger('django')


class UserRegisterForm(forms.Form):
    email = forms.EmailField(required=True, max_length=50, error_messages={'require': "请输入邮箱地址"})
    username = forms.CharField(required=True, error_messages={'require': "请输入用户名"}, max_length=30, min_length=2,
                               validators=[
                                   validators.RegexValidator(regex=r'^[\u4E00-\u9FA5A-Za-z0-9]{2,15}$',
                                                             message="用户名只能包括中文,字母,数字")])
    password = forms.CharField(required=True, error_messages={'require': "请输入密码"}, min_length=6, max_length=18,
                               validators=[
                                   validators.RegexValidator(regex=r'[\w.@+-_?&%$)!]{6,18}$',
                                                             message="请输入合法的密码")])
    repassword = forms.CharField(required=True, error_messages={'require': "请再次输入密码"}, min_length=6, max_length=18,
                                 validators=[
                                     validators.RegexValidator(regex=r'[\w.@+-_?&%$)!]{6,18}$',
                                                               message="请输入合法的密码")])
    captcha = CaptchaField(required=True, error_messages={'invalid': '验证码输入错误!'})

    def clean_email(self):
        email = self.cleaned_data.get('email', '')
        exists = User.objects.filter(email=email).exists()
        if exists:
            logger.info("【{email}】邮箱已经存在!".format(email=email))
            raise forms.ValidationError("邮箱已经存在!")
        return email

    def clean_username(self):
        username = self.cleaned_data.get('username', '')
        exists = User.objects.filter(username=username).exists()
        if exists:
            logger.info("【{username}】用户名已存在!".format(username=username))
            raise forms.ValidationError("该用户名已存在!")
        return username

    def clean(self):
        clean_data = super().clean()
        password = self.cleaned_data.get('password', '')
        repassword = self.cleaned_data.get('repassword', '')
        if password != repassword:
            logger.info("两次密码不一致!")
            raise forms.ValidationError(message="两次密码不一致!")
        return clean_data

注册视图和注册激活视图

编写\myblog\system\views.py

添加以下内容

import logging

from django.db import transaction
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views.generic.base import View

from system import forms
from system.models import User, EmailType
from system.tasks import send_email

logger = logging.getLogger('django')


class UserRegisterView(View):

    def get(self, request):
        register_form = forms.UserRegisterForm()
        return render(request, "user/register.html", {'register_form': register_form})

    @transaction.atomic
    def post(self, request):
        register_form = forms.UserRegisterForm(request.POST)
        if register_form.is_valid():
            email = register_form.cleaned_data['email']
            username = register_form.cleaned_data['username']
            password = register_form.cleaned_data['password']
            User.objects.create_user(username=username, email=email, password=password)
            send_email(EmailType.ACTIVE, username, password)
            return redirect(reverse("sys:login"))
        else:
            logger.info("注册表单验证未通过")
            return render(request, "user/register.html", {'register_form': register_form})


class UserActiveView(View):

    def get(self, request, code):
        record = EmailRecord.objects.filter(code=code).first()
        if record:
            receiver = record.receiver
            receiver.is_active = True
            receiver.save()
        return render(reverse("sys:login"))

路由绑定

编辑\myblog\system\urls.py

修改成以下内容

from django.urls import path
from system import views

urlpatterns = [
    path('register', views.UserRegisterView.as_view(), name='register'),
 path('active/<str:code>',views.UserActiveView.as_view(), name='register_active'),
]

发表评论 取消回复

电子邮件地址不会被公开。

请输入以http或https开头的URL,格式如:https://oneisall.top