django form组件 Cookie与Session组件

django 之 form组件

<body>
<h1>注册页面</h1>
<form action="" method="post">
    <p>username:
        <input type="text" name="username">
        <span>{{ errors.username }}</span>
    </p>
    <p>password:
        <input type="text" name="password">
        <span>{{ errors.password }}</span>
    </p>
    <input type="submit">
</form>

</body>
reg.html
def reg(request):
    errors = {'username':'', 'password':''}
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if 'sb' in username:
            errors['username'] = '用户名不能有sb'
        if password == '123':
            errors['password'] = '密码过于简单,请重新设置'
    return render(request, 'reg.html', locals())
手动实现注册验证功能

 

1. django form组件三个功能

渲染标签
校验数据
展示信息
注意:前端初步校验,可以不做,后端必须校验 !!!

2. 校验数据

第一步:建立form类

第二步:实例化产生form对象

第三步:查看该对象form_obj的信息

form_obj.is_valid()   校验是否有效:所有字段验证通过,返回True
form_obj.errors       错误信息提示:所有未通过校验的字段及错误提示
form_obj.cleaned_data 校验通过的数据

form组件校验数据规则:

从上往下依次取值校验
校验通过的数据,放入cleaned_data
校验未通过数据,放入errors,当全部通过,errors清空
多传入的数据,不会处理
form中所有字段默认必须传值(required=True)

类中字段基本校验全部通过后,需进行进一步的校验:钩子函数

局部钩子函数:单个字段校验

全局钩子函数:多个字段校验

from django.core.exceptions import ValidationError
class
MyForm(forms.Form): ..... def clean_name(self): # 局部钩子 name = self.cleaned_data.get('name') if '666' in name:
        # 1.主动抛异常
            raise ValidationError('光喊666是不行的')

       # 2.自定义异常
self.add_error(
'name', '光喊666是不行的') return name # 为兼容性考虑,加上return def clean(self):  # 全局钩子 password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if not password == confirm_password: self.add_error('confirm_password', '两次密码不一致!!') return self.cleaned_data

 

前端取消校验:

 

form标签,添加novalidate属性

右键检查,Elements里面直接修改

3. 渲染标签

from django import forms


class MyForm(forms.Form):
    name = forms.CharField(max_length=6)
    password = forms.CharField(max_length=8, min_length=3)
    email = forms.EmailField()

第一种渲染方式:

封装程度高,扩展性差,用于测试方便快捷    

def reg(request):
    form_obj = MyForm()  # 生成一个空对象
    return render(request, 'reg.html', locals())
<h2>第一种渲染方式</h2>
{{ form_obj.as_p }}
{{ form_obj.as_ul }}

第二种渲染方式

只渲染获取用户输入的input框,其他提交按钮等需要手动添加

from django import forms


class MyForm(forms.Form):
    name = forms.CharField(max_length=6, label='用户名')
    password = forms.CharField(max_length=8, min_length=3)
    email = forms.EmailField()


def reg(request):
    form_obj = MyForm()  # 生成一个空对象
    return render(request, 'reg.html', locals())
<h2>第二种渲染方式</h2>
<form action="">
    <p>{{ form_obj.name.label }}{{ form_obj.name }}</p>
    <p>{{ form_obj.password.label }}{{ form_obj.password }}</p>
    <p>{{ form_obj.email.label }}{{ form_obj.email }}</p>
    <input type="submit">
</form>

第三种渲染方式

<h2>第三种渲染方式</h2>
<form action="">
    {% for foo in form_obj %}
        <p>{{ foo.label }}{{ foo }}</p>
    {% endfor %}
    <input type="submit">
</form>

 

4. 展示信息

form组件提交数据如果数据不合法,页面上会保留之前用户输入的信息
在使用form组件对模型表进行数据校验的时候,只需要保证字段一致
在创建的对象的时候直接**form_obj.cleaned_data

提示错误信息时:

{{ foo.errors }} 结果为列表,格式为ul

{{ foo.errors.0 }}取出结果,变为正常格式

5. 常用字段

initial           初始值

error_messages    重写错误信息

Password          隐藏input框密码

radioSelect       圆形点,单选,单radio值为字符串

Select      单选框

SelectMultiple  多选框

CheckBox      方形勾,单选

CheckboxSelectMultiple   方形勾,多选

应用实例

from django import forms
from django.forms import widgets


class MyForm(forms.Form):  # 按照form组件写一个类
name
= forms.CharField(max_length=6, label='用户名', error_messages={ 'max_length': '用户名最长6位', 'required': '用户名不能为空', }) password = forms.CharField(max_length=8, min_length=3, error_messages={ 'max_length': '密码最长6位', 'min_length': '密码最少3位', 'required': '密码不能为空', }, widget=widgets.PasswordInput(attrs={'class': 'c1 form-control'})) # attrs 设置标签样式 confirm_password = forms.CharField(max_length=8, min_length=3, error_messages={ 'max_length': '确认密码最长6位', 'min_length': '确认密码最少3位', 'required': '确认密码不能为空', }, widget=widgets.PasswordInput(attrs={'class': 'form-control'})) gender = forms.ChoiceField( choices=((1, ''), (2, ''), (3, '保密')), label='性别', initial=3, widget=forms.widgets.RadioSelect() ) hobby = forms.ChoiceField( choices=((1, '篮球'), (2, '足球'), (3, '双色球')), label='爱好', initial=3, # 默认值 widget=forms.widgets.Select() # 单选 ) interest = forms.MultipleChoiceField( choices=((1, '看书'), (2, '练字'), (3, '绘画')), label='兴趣', initial=[1, 3], widget=forms.widgets.SelectMultiple() # 多选 ) keep = forms.ChoiceField( label='是否记住密码', initial='checked', widget=forms.widgets.CheckboxInput() ) email = forms.EmailField(error_messages={ 'invalid': '邮箱格式不正确', 'required': '邮箱不能为空' }) keep = forms.ChoiceField( label='是否记住密码', initial='checked', widget=forms.widgets.CheckboxInput() ) def clean_name(self): # 局部钩子 name = self.cleaned_data.get('name') if '666' in name: self.add_error('name', '光喊666是不行的') return name # 为兼容性考虑,加上return def clean(self):  # 全局钩子 password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if not password == confirm_password: self.add_error('confirm_password', '两次密码不一致!!') return self.cleaned_data
# 使用form组件实现注册方式
def reg(request): form_obj = MyForm() # 生成一个空对象 if request.method == 'POST': form_obj = MyForm(request.POST) # 实例化form对象,把post提交的数据直接传入,前后对象名称一致 if form_obj.is_valid():  # 调用form_obj校验数据的方法 models.User.objects.create(**form_obj.cleaned_data) return render(request, 'reg.html', locals())

页面渲染信息

<h2>MyForm</h2>
<form action="" method="post" novalidate>
    {% for foo in form_obj %}
        <p>{{ foo.label }}{{ foo }}<span>{{ foo.errors.0 }}</span></p>
    {% endfor %}
    <input type="submit">
</form>

 

 

 

django 操作 Cookie,Session

http协议四大特性

1. 基于TCP/IP作用于应用层的协议

2. 基于请求响应

3. 无状态

4. 无链接

cookie,session 即用于保存客户登录状态

cookie:保存在客户端浏览器上的键值对,安全性较差,保存的串一般为服务端识别客户端设置的唯一值(相当于id,<4KB)

session:保存在服务端上的键值对,和客服端访问时携带的串相匹配,识别不同用户取出对应私密信息(可以大于4KB)

django 操作 Cookie

服务端产生随机的串儿返回给客户端,服务端将信息存起来('随机字符串':'信息')

将以下👇路径设置关掉,网站将失去登录、保存状态的功能

Google浏览器>设置>高级>隐私设置和安全性>网站设置>权限>Cookie>允许网站保存和读取Cookie数据

django视图层函数return的HttpResponse、render、redirect终归为HttpResponse对象:

设置cookie

obj = HttpResponse()
return obj
obj = render()
return obj
obj = redirect()
return obj


# 给浏览器设置cookie,将于此时操作:
obj.set_cookie('','',expires=超时登录秒)   
return obj
# 注意:max_age设置超时登录,IE不能识别,多用expires

获取cookie 

 

request.COOKIES.get('name')
request.COOKIES['name']

删除cookie

obj.delete_cookie('值')

应用实例:

1. 没有登录不能访问其他页面,访问时直接跳转到登录页面

2. 装饰器内通过target_path = request.get_full_path()获取用户想访问的路径,给login路径添加get参数login/?next='%s' % target_path

3. login视图函数通过request.GET.get('next')获取用户想访问的路径

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^home/', views.home),
    url(r'^reg/', views.reg),
    url(r'^login/', views.login),
    url(r'^index/', views.index),
    url(r'^logout/', views.logout),
]

   视图层views

from django.shortcuts import render, HttpResponse, redirect


def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'jason' and password == '123':
            old_path = request.GET.get('next')  # 获取原登录目标
            if old_path:
                obj = redirect(old_path)  # 登录成功,跳转原目标网页
            else:
                obj = redirect('/home/')  # 直接开登录界面,设置home为跳转页面
            # 登录成功,给浏览器设置一个cookie
            obj.set_cookie('name', 'jason', expires=3600*24*7)  # 设置超时登录时间,单位为秒
            return obj
    return render(request, 'login.html')


def index0(request):
    if request.COOKIES.get('name'):
        return HttpResponse('index,登陆可见!!')
    return redirect('/login/')


from functools import wraps


def login_auth(func):
    @wraps(func)  # 装饰器修复
    def inner(request, *args, **kwargs):
        old_path = request.get_full_path()    # 获取验证登录前访问地址
        if request.COOKIES.get('name'):    # 校验cookie
            return func(request, *args, **kwargs)
        return redirect("/login/?next=%s" % old_path)  # 携带访问目标地址
    return inner


@login_auth
def index(request):
    return HttpResponse('index,登陆可见!!')


@login_auth
def home(request):
    return HttpResponse('home页面,登录可见!!')


@login_auth
def reg(request):
    return HttpResponse('reg页面,登录可见!!')


# 删除cookie
def logout(request):
    rep = redirect('/login/')
    rep.delete_cookie('name')  # 删除用户浏览器上设置的usercookie值
    return rep

 django 操作 Session

关于session:

django 默认的session存活时间14天 *******

一个浏览器固定占一行session信息,代码中设置多行将会加密到一行中,不影响取值

设置session将会执行三件事:

1. 生成一个随机字符串

2. django表中存储该随机字符串与数据记录:执行后在内存中产生临时缓存,经过SessionMiddleware保存到数据库中

3. 将随机字符串发送给客户端浏览器,浏览器生成一个sessionid键存放session值

取出session时,经过以下步骤:

1. django自动获取浏览器随机字符串,去django session表比对

2. 比对成功,将随机对应的字符串对应的数据,赋值给request.session

3. 通过request.session操作该数据(不存在也不会影响其他代码)

request.session['name'] = 'jason'  # 设置
request.session.get('name') #获取
request.session.delete() # 删除当前会话所有Session(数据库)
request.session.flush()  # 删除当前会话数据及Cookie(数据库、浏览器)
# 获取、设置、删除Session中数据
request.session['k1']
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在则不设置
del request.session['k1']


# 所有 键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()

# 会话session的key
request.session.session_key

# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()

# 检查会话session的key在数据库中是否存在
request.session.exists("session_key")

# 删除当前会话的所有Session数据
request.session.delete()
  
# 删除当前的会话数据并删除会话的Cookie。
request.session.flush() 
    这用于确保前面的会话数据不可以再次被用户的浏览器访问
    例如,django.contrib.auth.logout() 函数中就会调用它。

# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
    * 如果value是个整数,session会在些秒数后失效。
    * 如果value是个datatime或timedelta,session就会在这个时间后失效。
    * 如果value是0,用户关闭浏览器session就会失效。
    * 如果value是None,session会依赖全局session失效策略。
session相关方法

  设置session的超时时间:

如果value是个整数,session会在些秒数后失效。
如果value是个datatime或timedelta,session就会在这个时间后失效。
如果value是0,用户关闭浏览器session就会失效。
如果value是None,session会依赖全局session失效策略。

request.session.set_expiry(value)

应用实例

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^set_session/', views.set_session),
    url(r'^get_session/', views.get_session),
    url(r'^delete_session/', views.delete_session),
    url(r'^flush_session/', views.flush_session),
]
def set_session(request):
    request.session['name'] = 'jason'
    request.session['name1'] = 'egon'
    request.session['name2'] = 'tank'
    request.session['name3'] = 'nick'
    request.session['name4'] = 'sean'
    return HttpResponse('ok')

def get_session(request):
    print(request.session.get('name'))
    print(request.session.get('name1'))
    print(request.session.get('name2'))
    print(request.session.get('name3'))
    print(request.session.get('name4'))
    return HttpResponse('ok')


def delete_session(request):
    request.session.delete()
    return HttpResponse('ok')


def flush_session(request):
    request.session.flush()
    return HttpResponse('ok')

设置session时,数据库中的表不存在,将会报错

posted @ 2019-06-18 17:40  zhoyong  阅读(135)  评论(0编辑  收藏  举报