day74

## 0 form组件校验源码

```python
1 读的入口是:
    form.is_valid()--->self.errors(BaseForm类)---》self.full_clean()(BaseForm类)---self._clean_fields(局部数据校验)和self._clean_form(全局数据校验)
2 self._clean_fields(BaseForm类)
        for name, field in self.fields.items():
            try:
                # 字段自己的校验(最大值,最小值,是不是邮箱格式)
                value = field.clean(value)
                self.cleaned_data[name] = value
                if hasattr(self, 'clean_%s' % name): # 反射判断有没有clean_字段名
                    value = getattr(self, 'clean_%s' % name)()
                    self.cleaned_data[name] = value
            except ValidationError as e:
                self.add_error(name, e)
                
3 self._clean_form(BaseForm类)  全局钩子
     try:
           cleaned_data = self.clean()  # self.clean执行的是自己类的clean方法
        except ValidationError as e:
           self.add_error(None, e)
        
面向切面编程(AOP  OOP:面向对象编程)
```



## 1 django中cookie的使用

```python
# 0 会话跟踪,会话保持
# 1 cookie规范
    -记住:当前网站在浏览器上cookie个数和大小有限制
     -Cookie大小上限为4KB; 
     -一个服务器最多在客户端浏览器上保存20个Cookie; 
     -一个浏览器最多保存300个Cookie;
# 2 django中操作cookie
    -增:obj.set_cookie('key','value')
    -删: obj.delete_cookie('key')  # 设置过期
    -查: request.COOKIES.get('key')
    -改: obj.set_cookie('key','value1')
# 3 带签名的cookie(加盐,加密)
    -增:obj.set_signed_cookie('name','lqz','123')
    -删: obj.delete_cookie('name')  # 设置过期
    -查: request.get_signed_cookie('name',salt='123')
    -改: obj.set_signed_cookie('name','lqz','123')
```



## 2 cookie版登陆校验

### 路由

```python
# cookie版登录
path('login/', views.login),
path('order/', views.order),
path('logout/', views.logout),
path('userinfo/', views.userinfo),
```

### 视图函数

```python
## 登录认证装饰器

def login_auth(func):
    def inner(request, *args, **kwargs):
        # 登录校验
        name = request.COOKIES.get('name')
        if name:
            res = func(request, *args, **kwargs)
            return res
        else:
            path = request.get_full_path()
            return redirect('/login/?returnUrl=%s' % path)

    return inner


### cookie版登录
def login(request):
    if request.method == 'GET':

        return render(request, 'login.html')
    else:
        name = request.POST.get('name')
        password = request.POST.get('password')
        if name == 'lqz' and password == '123':
            # 写入cookie
            # 登录成功,重定向
            path = request.GET.get('returnUrl')
            if path:
                obj = redirect(path)
            else:
                obj = redirect('/index/')
            obj.set_cookie('name', name)
            return obj
        else:
            return HttpResponse('用户名或密码错误')


# def order(request):
#     name = request.COOKIES.get('name')
#     if name:
#         return render(request,'order.html')
#     else:
#         return redirect('/login')

## 装饰器版本(只要加了装饰器,一旦进入这个视图函数,就表明登录成了)
@login_auth
def order(request):
    return render(request, 'order.html')


@login_auth
def userinfo(request):
    return render(request, 'userinfo.html')


def logout(request):
    obj = HttpResponse('退出登录成功')
    obj.delete_cookie('name')
    return obj
```

### 模板

#### login.html

```html
<form action="" method="post">
    <p>用户名:<input type="text" name="name"></p>
    <p>密码:<input type="password" name="password"></p>
    <p><input type="submit" value="提交"></p>
</form>
```

#### order

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="/logout/">点我退出</a>
</body>
</html>
```

#### userinfo.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>用户信息页面</h1>
</body>
</html>
```

## 3 django中session的使用

```python
1 存在于服务端的键值对

2 同一个浏览器不允许登录多个账户,不同浏览器可以登录同一个账户

3 session的使用(必须迁移数据)
    -增:request.session['name']=lqz
    -查:request.session['name']
    -改:request.session['name']=egon
    -删:del request.session['name']
    -设置过期时间:request.session.set_expiry(10)
    
4 session的其它使用
    -request.session.setdefault('k1',123)
    -request.session.get('name',None)
    -del request.session['k1']
    
    -request.session.keys()
    -request.session.values()
    -request.session.items()
    -request.session.session_key # 获取那个随机字符串,django_session表中session_key字段
    
    -request.session.clear_expired() # 清除过期的session
    -request.session.exists("session_key") # 判断这个随机字符串(session_key字段),有没有数据
    -request.session.delete() # 删除所有的值,django_session表中删除当前登录者的这条记录
    -request.session.flush()  # 干了上面那个事,把cookie设置为过期
```



## 4 django中session的配置

```python
def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
                   domain=None, secure=False, httponly=False)

# key
# value
# max_age:过期时间,【传个数字,以秒计,过期时间,有默认值 (5天后过期:60*60*24*5)】
---了解
# expires:也是过期时间【传时间对象,date=datetime.timedelta()】
# path:默认 '/' 表示当前域下的所有路径  http://127.0.0.1:8000/lqz/dfd/
# domain:在那个域下有效
# secure:是否Https传输cookie
# httponly:cookie只支持http传输

1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)

2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置

3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 

4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

其他公用设置项:
SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)***记住

---了解
SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)

SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)

SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
```



## 5 cbv加装饰器

```python
from django.views import View
from django.utils.decorators import method_decorator
# 使用登录认证装饰器
# 用法一
# @method_decorator(login_auth,name='get')
# @method_decorator(login_auth,name='post')
class UserInfo(View):
    # 用法二
    @method_decorator(login_auth)
    def get(self, request, *args, **kwargs):
        return HttpResponse('userinfo get')
    
    
# 总结:两种用法
    -加在类上:@method_decorator(login_auth,name='get')
    -加载方法上:@method_decorator(login_auth)
```



## 6 中间件简介

```python
# 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能

# django内置中间件
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    
# views.py
from django.shortcuts import render, HttpResponse, redirect, reverse

import datetime


# Create your views here.
def add_cookie(request):
    obj = HttpResponse('add_cookie')
    obj.set_signed_cookie('name', 'welt', '123')  # set_signed_cookie (加盐,加密)

    # obj.set_cookie(self, key, value='', max_age=None, expires=None, path='/',
    #                domain=None, secure=False, httponly=False)
    # max_age:过期时间,【传数字,以秒计,有默认值  (设置5天后过期:60*60*24*5)】
    # ---了解
    # expires:也是过期时间,【传时间对象,date=datetime.timedelta()】
    # path:默认 '/' 表示当前域下的所有路径,访问这些路径都会携带cookie  http://127.0.0.1:8000/welt/asdasdfasf/
    # domain:设置cookie在哪个域下有效
    # secure:是否支持Https传输cookie
    # httponly:httponly=True,表示cookie只支持http传输

    # date = datetime.timedelta(days=5)   # 时间对象

    return obj


def get_cookie(request):
    print(request.COOKIES.get('name'))
    print(request.get_signed_cookie('name', salt='123'))  # 通过密钥获取明文cookie
    return HttpResponse('获取cookie')


def del_cookie(request):
    obj = HttpResponse('删除cookie')
    obj.delete_cookie('name')
    return obj


# 登录认证装饰器
def login_auth(func):
    def inner(request, *args, **kwargs):
        name = request.COOKIES.get('name')
        if name:
            res = func(request, *args, **kwargs)
            return res
        else:
            path = request.get_full_path()
            print(path)
            return redirect('/login/?returnUrl=%s' % path)
    return inner


def index(request):
    return render(request, 'index.html')


# def order(request):
#     name = request.COOKIES.get('name')
#     if name:
#         return render(request, 'order.html')
#     else:
#         return redirect('/login')
@login_auth
def order(request):
    return render(request, 'order.html')


@login_auth
def logout(request):
    obj = HttpResponse('已退出。')
    obj.delete_cookie('name')
    return obj


@login_auth
def reverse_test(request):
    return render(request, 'reverse.html')


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        name = request.POST.get('name')
        password = request.POST.get('password')

        if name == 'welt' and password == '818':

            path = request.GET.get('returnUrl')
            if path:
                obj = redirect(path)
            else:
                url = reverse('index')
                obj = redirect(url)
            obj.set_cookie('name', name)
            return obj
        else:
            return HttpResponse('认证失败')


# session

# 设置session
# django框架默认,把session信息存到数据库中了,django_session表
# 需要先进行数据库迁移操作
def set_session(request):
    request.session['name'] = 'welt'        # 设置session
    request.session['age'] = 16
    # request.session是个字典
    # 写了下面那一句话,干了如下几件事
    '''
        1 生成一个随机字符串asdfasdf,把随机字符串和name=welt数据加密存到django_session表中
                (不同的浏览器生成不同的随机字符串)
        2 会把这个随机字符串放到cookie中
            obj.set_cookie('sessionid',asdfasdf)
    '''
    return HttpResponse('session写入了')


def session_get(request):
    name = request.session.get('name')
    print(name)
    # print(request.session.keys())             # 取出所有key
    # print(request.session.values())           # 取出所有value
    # print(request.session.items())            # 取出所有键值对

    request.session.setdefault('k1', 123)        # 如果有值则不做修改,没有值则新增
    request.session.get('name', None)            # 如果没有get到,设置默认值为None
    del request.session['k1']                   # 删除

    print(request.session.session_key)          # 获取session_key(随机字符串)

    request.session.exists("session_key")       # 通过随机字符串(session_key字段)判断session_data中有没有数据
    request.session.delete()                    # 删除所有的值,即在django_session表中删除当前登录者的这条记录(cookie仍然保存)
    request.session.flush()                     # 删除记录,并把cookie设置为过期

    request.session.set_expiry(10)              # 设置过期时间
    request.session.clear_expired()             # 清除过期的session

    return HttpResponse('获取到了session')


from django.views import View
from django.utils.decorators import method_decorator
# 使用登录认证装饰器
# 用法一
# @method_decorator(login_auth,name='get')          # 第一个参数指定添加的装饰器,name指定给类中对应的方法加上装饰器
# @method_decorator(login_auth,name='post')
class UserInfo(View):
    # 用法二(直接在方法上添加装饰器)
    @method_decorator(login_auth)
    def get(self, request, *args, **kwargs):
        return HttpResponse('userinfo get')
# urls.py
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('add_cookie/', views.add_cookie),
    path('get_cookie/', views.get_cookie),
    path('del_cookie/', views.del_cookie),
    path('login/', views.login),
    path('', views.index, name='index'),
    path('order/', views.order),
    path('logout/', views.logout),
    path('reverse_test/', views.reverse_test, name='reverse_test'),
    path('set_session/', views.set_session),
    path('session_get/', views.session_get),
    # cbv加装饰器
    path('userinfo2/', views.UserInfo.as_view()),

]

 

posted @ 2020-10-23 15:09  板鸭没有腿  阅读(112)  评论(0)    收藏  举报