Django-零散知识点

Django-知识集合

能容简介

  1. cookie
  2. session
  3. 跨站请求保护
  4. 分页
  5. 序列化
  6. model模块
  7. CBV和FBV
  8. 模板渲染对象

一。cookie

cookie 是一种发送到客户浏览器的文本串句柄,并保存在客户机硬盘上,可以用来在某个WEB站点会话间持久的保持数据。
cookie特性:

  1. 一组一组键值对保存在用户浏览器
  2. 可以主动清除
  3. 也可以被“伪造”
  4. 跨域名cookie不共享
  5. 浏览器可以设置不接受cookie

cookie在浏览器中将会被放在一个一个源下,可以把浏览器中保存cookie的地方想象成一棵树,如果没有设置cookie的Domain和Path,则,该cookie将会被浏览器使用在该域名的顶级域名及它的所有子域名下。

django设置cookie通过接受的req对象来设置:

req.set_cookie(key, value='', max_age=None, expires=None, path='/',
                   domain=None, secure=None, httponly=None)
expires属性:
    指定了coolie的生存期,默认情况下coolie是暂时存在的,他们存储的值只在浏览器会话期间存在,当用户退出浏览器后这些值也会丢失。
    如果想让cookie存在一段时间,就要为expires属性设置为未来的一个过期日期。
    现在已经被max-age属性所取代,max-age用秒来设置cookie的生存期。
    max_age设置的值是数字,单位是秒,例如:max_age=10代表超时时间为10秒钟。
    expires对应的值是datetime对象,可以设置成expires=datetime.datetime.now()+datetime.timedelta(seconds=10)也是将超时时间延长10s

path属性:
    它指定与cookie关联在一起的网页。
    在默认的情况下cookie会与创建它的网页,与该网页处于同一目录下的网页以及与这个网页所在目录下的子目录下的网页关联。

domain属性:
    domain属性可以使多个web服务器共享cookie。domain属性的默认值是创建cookie的网页所在服务器的主机名。
    不能将一个cookie的域设置成服务器所在的域之外的域。
    例如让位于order.example.com的服务器能够读取catalog.example.com设置的cookie值。
    如果catalog.example.com的页面创建的cookie把自己的path属性设置为“/”,把domain属性设置成“.example.com”,那么所有位于catalog.example.com的网页和所有位于orlders.example.com的网页,以及位于example.com域的其他服务器上的网页都可以访问这个coolie。

secure属性:
    它是一个布尔值,指定在网络上如何传输cookie,默认是不安全的,通过一个普通的http连接传输。

httponly属性:
    只允许这个cookie使用在http协议里面,也就是说不允许客户端js什么的修改这个cookie的值,但是这个cookie是能够整体被替换的,所以这个安全性并没有什么卵用。。。。。。

django设置签名cookie方式:

rep.set_signed_cookie(key,value,salt='加密盐',**kwrgs)
    参数:
        key,              键
        value='',         值
        salt              加密盐

django获取cookie

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    参数:
        default: 默认值
           salt: 加密盐  //注意这里的salt要和签名cookie时候的salt设置一样才能拿到解密的cookie
        max_age: 后台控制过期时间

二。session

session机制:
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。一般这个cookie的名字都是类似于SEEESIONID。但cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。

生成随机字符串,并在服务端保存特定信息;

Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

使用以下的类型只需要在引擎修改下配置换成相应的类型就可以了。

  1. 数据库(默认)
  2. 缓存
  3. 文件
  4. 缓存+数据库
  5. 加密cookie

1. 数据库

配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)

    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_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)

使用

    def index(request):
        # 获取、设置、删除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的随机字符串(存在客户端浏览器中,也存在服务端的数据库中)
        request.session.session_key

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

        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")

        # 删除当前用户的所有Session数据
        request.session.delete("session_key")

示例:

def session(request):
    # request.session
    request.session['k1'] = 123  # 设置session
    # request.session['k1']
    print(request.session.session_key)  # 获得用户session的随机字符串(存在客户端浏览器中,也存在服务端的数据库中)
    return HttpResponse('session')


def index(request):  # 获得session
    return HttpResponse(request.session['k1'])  # 这里可以直接读取到session

2. 缓存

配置 settings.py

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


    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_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存

使用和数据库Session使用一样,只需要修改下配置就可以。

3.文件

配置 settings.py

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


    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_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存
使用和数据库Session使用一样,只需要修改下配置就可以。

4.缓存+数据库

 

数据库用于做持久化,缓存用于提高效率
a. 配置 settings.py
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
b. 使用
    同上

5. 加密cookie

a. 配置 settings.py
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
b. 使用
    同上

登陆认证实战

<form class="common_form" id="Form" method="post" action="/app01/login/">
    <div><h1 class="login_title">登录</h1></div>
    <div style="width: 600px">
        <div class="form_group"><input name="username" class="form-control" label='用户名' type="text" placeholder="用户名" require='true'></div>
    </div>
    <div style="width: 600px">
        <div class="form_group"><input name="password" class="form-control" label='密码' type="password" placeholder="密码" require='true'></div>
    </div>
    <div class="form_group"><input class="btn btn-info form_btn" type="submit" value="登录"></div>
</form>
def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "zhangsan" and password == "123456":
            request.session["IS_LOGIN"] = True  #创建session
            return redirect("/app01/home/")
    return render(request,"app01/login.html")

def home(request):
    islogin = request.session.get("IS_LOGIN",False)
    if islogin:#如果用户已登录
        return render(request,"app01/menus.html")
    else:
        return redirect("/app01/login/")

def logout(request):#退出
    try:
        del request.session['IS_LOGIN']
    except KeyError:
        pass
    return redirect("/app01/login/")

三。跨站请求保护

一、简介

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:
  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

二、应用

1、普通表单

veiw中设置返回值:
  return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
     或者
     return render(request, 'xxx.html', data)

html中设置Token:
  {% csrf_token %}

2、Ajax

对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

view.py

from django.template.context import RequestContext
# Create your views here.
def test(request):

    if request.method == 'POST':
        print request.POST
        return HttpResponse('ok')
    return  render_to_response('app01/test.html',context_instance=RequestContext(request))







text.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    {% csrf_token %}
    <input type="button" onclick="Do();"  value="Do it"/>
    <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
    <script src="/static/plugin/jquery/jquery.cookie.js"></script>
    <script type="text/javascript">
        var csrftoken = $.cookie('csrftoken');

        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
        $.ajaxSetup({  //设置ajax发送之前做的操作,在data里面加上一个键值对
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
        function Do(){

            $.ajax({
                url:"/app01/test/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });

        }
    </script>
</body>
</html>

四。分页

见 分页

五。序列化

关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。

#1.serializers

from django.core import serializers  #django内部提供的一个序列化对象的方法
ret = models.BookType.objects.all()  #通过all或者filter这种方式拿到的queryset对象可以通过serializers进行序列化
data = serializers.serialize("json", ret)

#2.json.dumps

import json
#ret = models.BookType.objects.all().values('caption')  #通过values或者values_list方式拿到的数据,可以直接被list强转之后再通过json.dumps进行序列化
ret = models.BookType.objects.all().values_list('caption')
ret=list(ret)
result = json.dumps(ret)


#由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:


import json
from datetime import date
from datetime import datetime

class JsonCustomEncoder(json.JSONEncoder):

    def default(self, field):
        if isinstance(field, datetime):
            return field.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(field, date):
            return field.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, field)

print(json.dumps(datetime.now(),cls=JsonCustomEncoder))

六。model模块

七。CBV和FBV

django里面的views里面支持两种处理请求的方式:

  • CBV—->views里面处理请求使用类
  • FBV—->views里面处理请求使用函数

使用视图函数处理请求的方式就不赘述了,之前一直是这种方式。
下面介绍使用类处理请求的方式。

首先在urls里面定义方式需要改变:

 

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.Login.as_view()),
]

要将之前的函数名称改成类名.as_view()方式,之后在views里面导入views模块:

from django import views
from django.utils.decorators import method_decorator #用来在类里面的函数视图函数中加上装饰器时使用

之后定义类继承自views.View:

 

def outer(func):
    def wrapper(req,*args,**kwargs):
        print("xxxxxxx")
        return func(req,*args,*kwargs)
    return wrapper

class Login(views.View):

    def dispatch(self, request, *args, **kwargs):
        if request.method=="GET":
            # return HttpResponse("xxx")
            pass
        ret=super(Login, self).dispatch(request, *args, **kwargs)
        print(111)
        return ret

    @method_decorator(outer)
    def get(self,req,*args,**kwargs):
        return render(req,"login.html")

    @method_decorator(outer)
    def post(self,req,*args,**kwargs):
        return render(req,"login.html",{"msg":"hello post"})

至于Login继承自views.View,而其父类中有一个方法dispatch,这个方法用来分发请求到不同的处理视图函数中,继承下这个类的子类中重写这个方法可以在视图函数处理请求之前和处理请求之后做一些操作。(甚至可以把装饰器装饰在这上面)

导入的method_decorator方法用来在类中的视图函数前面加上装饰器,把装饰器当做参数传递给method_decorator函数中。

八。模板渲染对象:

在django的模板语言中,可以使用.来获取对象的属性和方法,那么,当这个对象有同名的属性和方法时,模板语言调用对象的属性,而当对象中没有这个属性时,则调用该对象的方法。

class testobj:
    def __init__(self,name):
        self.name=name
    def name(self):
        return "xiaoming2"

def test(req):
obj=testobj("xiaoming")

    return render(req,"test.html",{"obj":obj})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>test template</h1>
    <h1>{{ obj.name }}</h1>
</body>
</html>

页面拿到的值是xiaoming,而当把self.name改成self.aname时则页面拿到的是xiaoming2

 

posted @ 2016-12-23 11:26  runnering  阅读(58)  评论(0)    收藏  举报