Django学习笔记(3):登录功能2

Django学习笔记(3):登录功能2

参考:
Django 2.0 项目实战: 扩展Django自带User模型,实现用户注册与登录
Django 2.0 项目实战 (2): 查看与编辑用户个人资料,扩展Django自带后台User Admin
Django 2.0 项目实战 (3): 用户重置密码与退出登录

目标

对Django自带user模型的访问,实现注册登录
代码版本:Django0619C

User模型

Django Auth模块自带User模型所包含字段
username:用户名
email: 电子邮件
password:密码
first_name:名
last_name:姓
is_active: 是否为活跃用户,默认是True
is_staff: 是否为员工。默认是False
is_superuser: 是否为管理员,默认是False
date_joined: 加入日期,系统自动生成。
在User模型的基础上扩展如下字段:
自定义的UserProfile模型
user: 与User是1对1关系
org:组织机构名
telephone: 电话
mod_date: 最后修改日期。系统自动生成

步骤

1.创建一个APP,命名为users
打开Terminal窗口,在命令行输入如下命令:
python manage.py startapp users
操作成功后,项目中增加一个user目录,修改项目中的settings.py,将’users’ 加到INSTALLED_APPS里

#修改settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'login',
    'users',
]

2.建立UserProfile模型
我们并没有改变Django Auth自带的User模型,也没有建立新的User模型。UserProfile只是对User模型的扩展。找到users/models.py, 并创建如下UserProfile模型。由于我们引用了Django Auth自带的User模型,所以我们必需开始先把它import进来。

#users/models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    org = models.CharField('Organization', max_length=128, blank=True)
    telephone = models.CharField('Telephone', max_length=50, blank=True)
    mod_date = models.DateTimeField('Last modified', auto_now=True)

    class Meta:
        verbose_name = 'User Profile'
    def __str__(self):
        return "{}".format(self.user.__str__())

然后你可以在终端输入以下命令,就可以创建UserProfile的数据表。

python manage.py makemigrations
python manage.py migrate
3.配置url
首先配置users/urls.py
从URL配置科研看出我们要实现的6个功能。下面是users/urls.py里的全部代码。你应该注意到,我们给动态链接/register/取了个名字’register’, 这样我们就可以在html模板里可以通过{% url ‘users:register’ %}调用这个链接了。

在这里插入代码片
from django.urls import path,re_path
from users import views
app_name='users'
urlpatterns = [
     re_path(r'^register/$', views.register, name='register'),
    re_path(r'^login/$', views.login, name='login'),
    re_path(r'^user/(?P<pk>\d+)/profile/$', views.profile, name='profile'),
    re_path(r'^user/(?P<pk>\d+)/profile/update/$', views.profile_update, name='profile_update'),
    re_path(r'^user/(?P<pk>\d+)/pwdchange/$', views.pwd_change, name='pwd_change'),
    re_path(r'^logout/$', views.logout, name='logout'),
]

然后配置顶层的Django0619/urls.py,把我们这个app的URLs也加进去,如下所示。这样当用户访问/accounts/register/时,浏览器会调用views.py里的register函数。

#在原有代码上增加
from users import views

urlpatterns = [
   ...
    url(r'^accounts/',include('users.urls')),
]

4.创建form
我们需要编写register和login两个视图, 让用户通过表单向我们提交数据,并处理这些数据。因为这两个视图都需要用表单,所以我们先在users目录下新建forms.py, 然后创建两个form,一个RegistrationForm,一个LoginForm。代码如下:

#forms.py
from django import forms
from django.contrib.auth.models import User
import re
def email_check(email):
    pattern = re.compile(r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?")
    return re.match(pattern, email)

class RegistrationForm(forms.Form):
    username = forms.CharField(label='用户名', max_length=50) #label='用户名Username',
    email = forms.EmailField(label='电子邮件',)# Email
    password1 = forms.CharField(label='密码', widget=forms.PasswordInput)#Password
    password2 = forms.CharField(label='确认密码', widget=forms.PasswordInput)#Password Confirmation
    # Use clean methods to define custom validation rules
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if len(username) < 6:
            raise forms.ValidationError("Your username must be at least 6 characters long.")
        elif len(username) > 50:
            raise forms.ValidationError("Your username is too long.")
        else:
            filter_result = User.objects.filter(username__exact=username)
            if len(filter_result) > 0:
                raise forms.ValidationError("Your username already exists.")
        return username
    def clean_email(self):
        email = self.cleaned_data.get('email')
        if email_check(email):
            filter_result = User.objects.filter(email__exact=email)
            if len(filter_result) > 0:
                raise forms.ValidationError("Your email already exists.")
            else:
                raise forms.ValidationError("Please enter a valid email.")
        return email
    def clean_password1(self):
        password1 = self.cleaned_data.get('password1')
        if len(password1) < 6:
            raise forms.ValidationError("Your password is too short.")
        elif len(password1) > 20:
            raise forms.ValidationError("Your password is too long.")
        return password1
    def clean_password2(self):
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Password mismatch. Please enter again.")
        return password2
class LoginForm(forms.Form):
    username = forms.CharField(label='用户名', max_length=50,error_messages={"required": "用户名必填"})
    password = forms.CharField(label='密  码', widget=forms.PasswordInput,error_messages={"required": "密码必填"})
    Log_auth="False"
    # Use clean methods to define custom validation rules
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if email_check(username):
            filter_result = User.objects.filter(email__exact=username)
            if not filter_result:
                raise forms.ValidationError("This email does not exist.")
        else:
            filter_result = User.objects.filter(username__exact=username)
            if not filter_result:
                raise forms.ValidationError("This username does not exist. Please register first.")
        return username

千万不要上面的代码吓到。之所以代码这么长是因为我们用clean方法加入了很多表单验证项,比如检查用户名是否过短,用户名是否已经存在。如果你把表单验证拿掉,其实代码非常少。我之所以加上这些验证规则,是让你了解最真实的网站开发。
当然你也可以不用新建forms.py而直接在html模板里写表单,但我并不建议这么做。用forms.py的好处显而易见: 所有的表单在一个文件里,非常便于后期维护,比如增添或修订字段。forms.py可通过clean方法自定义表单验证,非常便捷。不用在views.py里再进行表单验证(比如检查用户是否已存在),逻辑上更清晰。
5.编写view
修改users/views.py,创建register函数,用于处理用户注册过程。

在这里插入代码片
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.models import User
from .models import UserProfile
from django.contrib import auth
from .forms import RegistrationForm, LoginForm
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.contrib.auth.decorators import login_required

def register(request):
    if request.method =='POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            email = form.cleaned_data['email']
            password = form.cleaned_data['password2']
             # 使用内置User自带create_user方法创建用户,不需要使用save()
            user = User.objects.create_user(username=username, password=password, email=email)
             # 如果直接使用objects.create()方法后不需要使用save()
            user_profile = UserProfile(user=user)
            user_profile.save()          
            return HttpResponseRedirect("/accounts/login/")
        else:
            return render(request, 'users/registration.html', {'form': form})
    else:
        form = RegistrationForm()
        return render(request, 'users/registration.html', {'form': form})      

我们先看下views.register函数是怎么工作的:

当用户通过POST方法提交表单,我们先验证表单RegistrationForm的数据是否有效。如果有效,我们先用Django User模型自带的create_user方法创建user对象,再创建user_profile。用户通过一张表单提交数据,我们实际上分别存储在两张表里。
如果用户注册成功,我们通过HttpResponseRedirect方法转到登陆页面,如果用户没有提交表单或不是通过POST方法提交表单,我们转到注册页面,生成一张空的RegistrationForm。

创建login函数,用于处理登录

在这里插入代码片
def login(request):
    errmsg = ""
    if request.method =='POST':
        print("POST")
        form = LoginForm(request.POST)  
        status = form.is_valid()      
        if status:          
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            user = auth.authenticate(username=username, password=password)
            if user is not None and user.is_active:               
                auth.login(request, user)
                form.Log_auth = "Ture"               
                return render(request, 'homepage.html', {'form': form})
            else: 
                errmsg = "密码错误!"            
                return render(request, 'users/login.html', {'form': form, 'err_msg': errmsg})             
        else        
            errmsg = "用户名或密码错误!"
            form = LoginForm()
            return render(request, 'users/login.html', {'form': form,'err_msg': errmsg})
    if request.method =='GET':      
        form = LoginForm()
        return render(request, 'users/login.html', {'form': form})

我们再看下views.login函数是怎么工作的:
当用户通过POST方法提交表单,我们先验证表单LoginForm的数据是否有效。如果有效,我们调用Django自带的auth.authenticate() 来验证用户名和密码是否正确。如果正确且用户是活跃的,我们调用auth.login()来进行登录。如果用户登录失败,会重新转到登录页面,并返回错误信息。如果用户登录成功,我们通过HttpResponseRedirect方法转到用户个人信息页面
如果用户没有提交表单或不是通过POST方法提交表单,我们转到登录页面,生成一张空的LoginForm
6.编写html模板
在users目录下创建/templates/users/文件夹,编写html模板registration.html和login.html。其目录结构应该如下图所示:
在这里插入图片描述
registration.html主要代码如下:

在这里插入代码片
<div class="fl form-box">
                <div class="tab">
                    <!--<h2 class="active">手机注册</h2>-->
                    <h2>注  册</h2>
                </div>
                <div class="tab-form">
                    <form method="post" action="" enctype="multipart/form-data">
                        {% csrf_token %}
                        {% for field in form %}
                            <div class="marb8">
                            {{ field.label_tag }}
                            </div>
                            <div class="fieldWrapper">
                                 {{ field }}{{ field.errors }}
                                {% if field.help_text %}
                                    <p class="help">{{ field.help_text|safe }}</p>
                                {% endif %}
                            </div>
                        {% endfor %}
                        <div class="marb8">
                        </div>
                        <div class="marb8">
                            <input class="btn btn-green" id= "jsLoginBtn" type="submit" value="注册并登录" />
                        </div>

                    </form>
                </div>
                <p class="form-p">已有账号?<a href="login.html">[立即登录]</a></p>
            </div>

login.html主要代码如下:

在这里插入代码片
<div class="fl form-box">
                <h2>帐号登录</h2>
                <form method="post" action="" enctype="multipart/form-data">
                {% csrf_token %}
                <div class="marb8">
                        <label>用户名</label>
                </div>
                <div class="form-group marb20 ">
                    <input type="text" name="username">
                </div>
                <div class="marb8">
                        <label>密 码</label>
                </div>
                <div class="form-group marb20 ">
                    <input type="password" name="password">
                </div>
                <div class="marb8">
                    {{ err_msg }}
                </div>

7.运行
python manage.py runserver
打开浏览器http://127.0.0.1:8000/
点击登录,在弹出的页面可测试登录功能
在这里插入图片描述
点击注册,在弹出的页面可测试注册功能
在这里插入图片描述
8小结:
本文利用Django 2.0实现了用户注册与登录的两个功能,扩展了Django自带的User模型,并分享了代码。接下来我会分享如何实现查看用户资料,允许用户修改自己资料,修改密码和退出登录的其它4个功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值