导航
导航
文章目录
  1. 前言
  2. 例子
    1. 例子四(1)
  3. 例子四(2)
  4. 问题二验证码
  5. 结束语

Django学习笔记(四)

前言

上两篇我们学习了MVT和Models进行数据库的操作,这一篇我们还是以实例来讲解,主要学习使用Django 编写一个 注册、登录、验证码的例子。

  • 我们将学到如下知识:
    • Django forms表单样式排版
    • 验证码实现的机制 cookies session 设置
    • Django request对象传值
    • Django 自带的用户登录判断

例子

快速上手还是多动手敲打键盘编写代码,多动手实现。直接上学例子学习,主要是先建立Django实现功能的思想,里面的细枝末节可以搜索一下相关的资料进行补充巩固学习。
这里介绍两种编写的方法,一种是自己设计用户登录注销管理cookies和session。另一种就是使用Django自带判断登录 注销等

例子四(1)

验证码的部分参考https://strcpy.me/index.php/archives/176/
每次获取的验证码都需要把上次生成的验证码消除。
准备工作
以后准备工作都是相同的,设置方面也是一直的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$python-admin startproject project  #创建项目
$python manage.py startapp blog #创建应用
#设置数据库、应用加载、模板文件路径
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django-test',
'USER': 'root',
'PASSWORD': 'seck@root...',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
)
TEMPLATES = [
{
'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',
],
},
},
]

项目的文件结构如图

首先编写models.py 创建数据库表结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
#-*- coding:utf-8 _*-
"""
author:seck
time: 2018/01/28
"""
from django import forms
from .views import *
class UserRegisterForm(forms.Form):
username = forms.CharField(label='用户名',max_length=50)
password = forms.CharField(label='密码',widget=forms.PasswordInput())
email = forms.EmailField(label='邮箱')
# captcha1=captcha()
class UserLoginForm(forms.Form):
username = forms.CharField(label='用户名', max_length=50)
password = forms.CharField(label='密码', widget=forms.PasswordInput())

编写forms.py

  • 创建类,继承form.Form
  • 页面根据类的对象自动创建html标签
  • 提交,request.POST
  • 封装到类的对象里,obj=UserInfo(request.POST)
  • 用户输入是否合法
  • obj.is_valid()
  • 全部合法,获取全部内容
  • obj.clean()
  • 只有有不合法
  • obj.errors
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #!/usr/bin/env python
    #-*- coding:utf-8 _*-
    """
    author:seck
    time: 2018/01/28
    """
    from django import forms
    from .views import *
    class UserRegisterForm(forms.Form):
    username = forms.CharField(
    required=True,
    error_messages={'required':'用户名不能为空'},
    label='用户名',max_length=50,widget=forms.TextInput(attrs={'placeholder': 'Username','class':'username11'}))
    password = forms.CharField(label='密码',widget=forms.PasswordInput())
    email = forms.EmailField(label='邮箱')
    # captcha1=captcha()
    class UserLoginForm(forms.Form):
    username = forms.CharField(required=True,
    error_messages={'required':'用户名不能为空'},label='用户名', max_length=50)
    password = forms.CharField(label='密码', widget=forms.PasswordInput())

attrs属性是定义在html中用户登录框的css属性名称,error_messages 确认输入的是否规范返回错误的信息比如required=True 如果没有填入用户名,就会显示“用户名不能为空”
细节参考http://www.cnblogs.com/zhaijunming5/category/892772.html
http://www.cnblogs.com/yangmv/p/5327477.html

编写views.py进行控制数据传送
关键点的信息就是使用session控制验证码的验证。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse,HttpResponseRedirect ,request
from captcha import *
from .forms import *
from .models import *
# Create your views here.
#首先显示
def index(request):
data=[]
try:
if request.session['username']:
seesion=request.session['username']
print seesion
if seesion:
data.append(seesion)
print "login success!"
except Exception , e:
print (e)
data.append('no login')
title="seck"
print request.COOKIES
# return HttpResponse("<img id='verifycode' src='/captcha/' alt='CheckCode'/>")
return render(request,'blog/index.html',{'title':title,'data':data},)
#验证码调用
def captcha(request):
Cap = Captcha(request)
Code =Cap.display()
return Code
#注册
def register(request):
if request.method == 'POST':
userform =UserRegisterForm(request.POST)
cap = request.POST.get('cap')
ca = Captcha(request)
if userform.is_valid():
username = userform.cleaned_data['username']
password = userform.cleaned_data['password']
email = userform.cleaned_data['email']
if ca.check(cap):
print "The code true"
else:
print "The code error!"
return HttpResponse("验证码不正确,请刷新后重新输入!")
if User.objects.filter(username=username):
print "The user exits"
return HttpResponse("用户名重复!")
else:
User.objects.create(username=username, password=password, email=email).save()
return HttpResponse('register success!')
else:
userform = UserRegisterForm()
return render(request,'blog/register.html',{'userform':userform,})
def login(request):
if request.method == "POST":
userform = UserLoginForm(request.POST)
print userform.errors.get('username')
if userform.is_valid():
username = userform.cleaned_data['username']
password = userform.cleaned_data['password']
user= User.objects.filter(username__exact=username,password__exact=password)
if user:
#Step1:生成随机字符串(seesionID)
#Step2:通过cookie发送给客户端
#Step3:服务端保存 session
print "seck"
# print user.values()[0][username]
request.session['username']=username
print request.session
# return render(request,'blog/index.html',{'userform':userform})
return HttpResponseRedirect('/')
else:
return HttpResponse('用户名或者密码错误!')
else:
print "stsrat"
userform=UserLoginForm()
return render(request,'blog/login.html',{'userform':userform})
def sign_out(request):
del request.session['username']
return HttpResponseRedirect('/')

urls.py 的设置
blog/urls.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python
#-*- coding:utf-8 _*-
"""
author:seck
time: 2018/01/28
"""
from django.conf.urls import include, url
from views import *
urlpatterns = [
# Examples:
# url(r'^$', 'blog_week_6.views.home', name='home'),
url(r'^captcha/$',captcha),
url(r'^login/$',login),
url(r'^register/$',register),
url(r'^sign_out/$',sign_out),
url(r'', index,name='index'),
]

根目录下的urls.py

1
2
3
4
5
6
7
8
9
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
# Examples:
# url(r'^$', 'blog_week_8.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'',include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
]

模板文件的代码
index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{title}}</title>
</head>
<body>
<h1>welcome {% if data %}{% for data in data%} {% if 'no' not in data %} {{data}} <a href="/sign_out/">退出</a> {% endif%} {% endfor %} {% endif %}</h1>
<a href="/login/">登录 </a>
<br>
<a href="/register/">注册 </a>
</body>
</html>

login.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{userform}}
<input type="submit" name="sumit" value="login">
</form>
<a href="/">首页 </a>
<br>
<a href="/register/">注册 </a>
</body>
</html>

register.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{userform}}
验证码 <input type="text" name="cap"> <img src="{{'/captcha/'}}">
<input type="submit" name="sumit" value="register">
</form>
<a href="/login/">登录 </a>
<br>
<a href="/">首页 </a>
</body>
</html>

项目代码https://github.com/Huseck/Django-study/tree/Django-study-4
本篇的运行结果图

例子四(2)

  • 主要关注的几个逻辑问题
    • 怎么判断用户名是否重名
    • 继承自带的auth.user表是否能添加我们还需要的字段
    • 使用DjangoCaptcha判断机制是否符合要求
    • forms继承的关系和判断form表单数据
    • 准备
    • 这里我们使用自带的auth_user实现注册、登录验证。
    • 安装pip install django-simple-captcha==0.5.6
    • 配置 settings.py
1
2
3
4
5
6
7
8
9
10
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'captcha',
)

根目录下的urls.py也要配置验证码的路由

1
2
3
4
5
urlpatterns = [
url(r'', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^captcha/', include('captcha.urls')),
]

之后我们生成默认的数据库,成功之后会发现是有captcha_captchastore表的
然后开始编写我们的forms表单,blog目录下创建forms.py文件代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python
#-*- coding:utf-8 _*-
"""
author:seck
time: 2018/02/09
"""
from django import forms
from captcha.fields import CaptchaField
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from .models import Users
class CreateUser(UserCreationForm):
#UserCreationForm 里面自带的会验证重名
username = forms.CharField(error_messages={'required':u"用户名不能为空"})
password = forms.CharField(widget=forms.PasswordInput(),error_messages={'required':u"密码不能为空"})
email = forms.CharField()
captcha = CaptchaField()
class Auth(AuthenticationForm):
username = forms.CharField(error_messages={'required': '用户名不能为空'})
password = forms.CharField(widget=forms.PasswordInput(),error_messages={'required':u"密码不能为空"})
captcha = CaptchaField()

我们编写一下视图函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#coding:utf-8
from django.shortcuts import render,redirect
from django.http import HttpResponse
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth import models
from django.contrib.auth.models import User
from .forms import CreateUser,Auth
def index(request):
return render(request,'blog/index.html')
def register(request):
createform = CreateUser(data=request.POST or None)
if request.method == "POST":
if createform.is_valid():
username = createform.clean_username()
password = createform.clean_password2()
email = createform.clean()['email']
#django 默认的user表创建用户使用create_user函数
user = User.objects.create_user(username=username,password=password,email=email)
user.save()
return HttpResponse(u"注册成功")
else:
error_msg = createform.errors
print error_msg
return render(request,'blog/register.html',{"errors":error_msg})
return render(request,'blog/register.html',{"createform":createform})
def auth(request):
authform = Auth(data=request.POST or None)
if request.method == "POST":
#判断输入的数据是否符合规则
if authform.is_valid():
login(request,authform.get_user())
return render(request,'blog/index.html',{})
else:
#如果数据不符合规则,就显示错误信息
error_msg=authform.errors
print authform.errors
return render(request, 'blog/login.html', {"userform": authform, "errors": error_msg})
return render(request,'blog/login.html',{"userform":authform})
def sign_out(request):
logout(request)
return redirect("/")

问题一验证重名
我们的CreateForm继承UserCreateForm 这个类继承User 这个又继承AbstractUser
然后找到关键位置

1
2
3
4
5
在文件site-packages\django\contrib\auth\models.py  394行左右找到
error_messages={
'unique': _("A user with that username already exists."),
})
也就是is_valid 方法判断error是否有错误存在判断出重名 username 是unique=True 值唯一的定义

问题二验证码

当我们登录或者注册一个用户的时候,浏览器点击返回,在用此验证码注册其他的账号时,验证码应该是失效的,django-simple-captcha满足。
问题三form表单的继承
我们继承了UserCreationForm 和AuthenticationForm进行数据的验证,使用自带的验证方法实现用户的注册和登录。

结束语

当django自带的数据表和验证方法不满足需求时,需要自行扩展接口功能,实现应用。

支持一下
扫一扫,支持作者

Powered by HyperComments