前面几篇博客完成了文章基本的增删改查:
接下来就要做下一个子任务------用户登录与注册
感谢大神的教程:Django搭建个人博客.
对于大部分网站来说,用户数据可谓是比较重要的数据了.而用户管理就是对用户数据的增删改查,自然也是十分重要.我们首先从用户登录开始.
由于用户管理和文章管理的功能不相同,所以我们再创建一个用户管理的app,专门用来做用户管理:
python manager.py startapp userprofile
然后就把这个app配置好.
在userprofile下创建一个forms.py文件:
from django import forms
from django.contrib.auth.models import User
# 登录表单
# 这里使用Form而不是ModelForm是因为用户登录不需要与数据库进行交互
class UserLoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField()
userprofile/views.py:
from django.shortcuts import render,HttpResponse,redirect
from django.contrib.auth import authenticate,login,logout
from django.http import HttpResponse
from userprofile.forms import UserLoginForm,UserRegisterForm
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
def user_login(request):
if request.method == 'POST':
user_login_form = UserLoginForm(data=request.POST)
if user_login_form.is_valid():
# .cleaned_data 清洗出合法数据
data = user_login_form.cleaned_data
# 检验账号、密码是否正确匹配数据库中的某个用户
# 如果均匹配则返回这个 user 对象
user = authenticate(username=data['username'], password=data['password'])
if user:
# 将用户数据保存在 session 中,即实现了登录动作
login(request, user)
return redirect("article:article_list")
else:
return HttpResponse("账号或密码输入有误。请重新输入~")
else:
return HttpResponse("账号或密码输入不合法")
elif request.method == 'GET':
user_login_form = UserLoginForm()
context = { 'form': user_login_form }
return render(request, 'userprofile/login.html', context)
else:
return HttpResponse("请使用GET或POST请求数据")
其中:
/templates/userprofile/login.html:
% extends "base.html" %} {% load staticfiles %}
{% block title %} 登录 {% endblock title %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-12">
<br>
<form method="post" action=".">
{% csrf_token %}
<div class="form-group">
<label for="username">账号label>
<input type="text" class="form-control" id="username" name="username">
div>
<div class="form-group">
<label for="password">密码label>
<input type="password" class="form-control" id="password" name="password">
div>
<button type="submit" class="btn btn-primary">提交button>
form>
div>
div>
div>
{% endblock content %}
修改一下tempalates/header.html,把登录的按钮加进去:
<ul class="navbar-nav">
...
<li class="nav-item">
<a class="nav-link" href="{% url 'article:article_list' %}">文章a>
li>
{% if user.is_authenticated %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ user.username }}
a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#">退出登录a>
div>
li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'userprofile:login' %}">登录a>
li>
{% endif %}
ul>
Personal_Blog/urls.py:
path('userprofile/', include('userprofile.url',namespace='userprofile')),
userprofile/url.py:
path('login/',views.user_login,name='login'),
然后运行程序就行.
有了用户登录,用户登出就简单了:
userprofile/views.py
# 引入logout模块
from django.contrib.auth import authenticate, login, logout
...
# 用户退出
def user_logout(request):
logout(request)
return redirect("article:article_list")
userprofile/url.py:
path('logout/',views.user_logout,name='logout'),
header.html:
# 改动 href 中的链接指向
<a class="dropdown-item" href='{% url "userprofile:logout" %}'>退出登录a>
然后运行程序就行.
userprofile/forms.py:
# 注册用户表单
class UserRegisterForm(forms.ModelForm):
# 复写User的密码
password = forms.CharField()
password2 = forms.CharField()
class Meta:
model = User
fields = ('username','email')
# 对两次输入的密码是否一致进行检查
def clean_password2(self):
data = self.cleaned_data
if data.get('password') == data.get('password2'):
return data.get('password')
else:
return forms.ValidationError("两次密码输入不一致")
userprofile/views.py:
# 用户注册
def user_register(request):
if request.method == "POST":
user_register_form = UserRegisterForm(data=request.POST)
if user_register_form.is_valid():
new_user = user_register_form.save(commit=False)
new_user.set_password(user_register_form.cleaned_data['password'])
new_user.save()
# 保存好数据后立即登录并返回博客列表页面
login(request, new_user)
return redirect("article:article_list")
else:
return HttpResponse("注册表单输入有误。请重新输入~")
elif request.method == "GET":
user_register_form = UserRegisterForm()
context = {'form': user_register_form}
return render(request, 'userprofile/register.html', context)
else:
return HttpResponse("请使用GET或POST请求数据")
userprofile/register.html
{% extends "base.html" %} {% load staticfiles %}
{% block title %} 登录 {% endblock title %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-12">
<br>
<form method="post" action=".">
{% csrf_token %}
<div class="form-group col-md-4">
<label for="username">昵称label>
<input type="text" class="form-control" id="username" name="username" required>
div>
<div class="form-group col-md-4">
<label for="email">Emaillabel>
<input type="text" class="form-control" id="email" name="email">
div>
<div class="form-group col-md-4">
<label for="password">设置密码label>
<input type="password" class="form-control" id="password" name="password" required>
div>
<div class="form-group col-md-4">
<label for="password2">确认密码label>
<input type="password" class="form-control" id="password2" name="password2" required>
div>
<button type="submit" class="btn btn-primary">提交button>
form>
div>
div>
div>
{% endblock content %}
在登录页面中添加:
uerprofile/login.html:
<div class="col-12">
<br>
<h5>还没有账号?h5>
<h5>点击<a href='{% url "userprofile:register" %}'>注册账号a>加入我们吧!h5>
<br>
<form method="post" action=".">
...
form>
div>
userprofile/url.py:
path('register/',views.user_register,name='register'),
然后运行项目就行.
相对于用户登录与注册,用户的删除需要更谨慎.
userprofile/views.py:
# @login_required是一个python装饰器.
# 装饰器可以在不改变某个函数内容的前提下,给这个函数添加一些功能.
# 具体来说,就是@login_required要求调用user_delete()函数时,用户必须登录
# 如果未登录则不执行函数,将页面重定向到'/userprofile/login/'地址去
# 装饰器确认用户已经登录后,允许调用user_delete(),
# 然后需要删除的用户id通过请求传递到视图中,
# 由if语句确认是否与登录的用户一致
# 成功后则退出登录并删除用户数据,返回博客列表页面
@login_required(login_url='/userprofile/login/')
def user_delete(request,id):
if request.method == "POST":
user = User.objects.get(id=id)
# 验证登录用户,待删除用户是否相同
if request.user == user:
# 退出登录,删除数据并返回博客列表
logout(request)
user.delete()
return redirect("article:article_list")
else:
return HttpResponse('你没有删除操作的权限')
else:
return HttpResponse("仅接收post请求")
改写header.html:
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#">我的博客a>
<div>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="{% url 'article:article_create' %}">写文章a>
li>
<li class="nav-item">
<a class="nav-link" href="{% url 'article:article_list' %}">文章a>
li>
{% if user.is_authenticated %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ user.username }}
a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#" onclick="user_delete()">删除用户a>
<a class="dropdown-item" href="{% url 'userprofile:logout' %}">退出登录a>
div>
li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'userprofile:login' %}">登录a>
li>
{% endif %}
ul>
div>
div>
nav>
{% if user.is_authenticated %}
<form
style="display:none;"
id="user_delete"
action="{% url 'userprofile:delete' user.id %}"
method="POST"
>
{% csrf_token %}
<button type="submit">发送button>
form>
<script>
function user_delete() {
// 调用layer弹窗组件
layer.open({
title: "确认删除",
content: "确认删除用户资料吗?",
yes: function(index, layero) {
$('form#user_delete button').click();
layer.close(index);
},
})
}
script>
{% endif %}
userprofile/url.py:
path('delete/' ,views.user_delete,name='delete'),
然后运行项目就可以了
本文是个人的一些学习笔记,如有侵权,请及时联系我进行删除,谢谢大家.