Session的使用

来源:互联网 发布:中央电视台网络电视 编辑:程序博客网 时间:2024/05/23 00:41

Session的使用

 

你可以用session 框架来存取每个访问者任意数据,这些数据在服务器端存储,并对cookie的收发进行了抽象。 Cookies只存储数据的哈希会话ID,而不是数据本身,从而避免了大部分的常见cookie问题。下面我们来看一下session的使用

 

首先要再Django中打开Sessions功能,当然再新版本的django中这大都是已经配置好的。你需要检查以下。

 

1. 编辑 MIDDLEWARE_CLASSES配置,确保 MIDDLEWARE_CLASSES 中包含 'django.contrib.sessions.middleware.SessionMiddleware'。

 

2. 确认 INSTALLED_APPS 中有'django.contrib.sessions'

 

3.settings.py

 

INSTALLED_APPS = (

   'django.contrib.admin',

   'django.contrib.auth',

   'django.contrib.contenttypes',

   'django.contrib.sessions',

   'django.contrib.messages',

   'django.contrib.staticfiles',

   'mysite',

   'books',

   'blog'

)

 

MIDDLEWARE_CLASSES = (

   'django.contrib.sessions.middleware.SessionMiddleware',

   'django.middleware.common.CommonMiddleware',

   'django.middleware.csrf.CsrfViewMiddleware',

   'django.contrib.auth.middleware.AuthenticationMiddleware',

   'django.contrib.auth.middleware.SessionAuthenticationMiddleware',

   'django.contrib.messages.middleware.MessageMiddleware',

   'django.middleware.clickjacking.XFrameOptionsMiddleware',

   'django.contrib.sessions.middleware.SessionMiddleware',

)

 

 

 

 

 

在View(视图)中使用Session

 

SessionMiddleware 激活后,每个传给视图(view)函数的第一个参数``HttpRequest``对象都有一个 session 属性,这是一个字典型的对象。

 

#设置session值

request.seesion["fav_color"]="blue"

 

#读取session值

fav_color=request.session["fav_color"]

 

#删除某个session值

del request.session["fav_color"]

 

#判断是否存在某个session值

if "fav_color" inrequest.session:

 

 

e.g.:

 

简单(但不很安全)的、防止多次评论方法

 

#mysite/urls.py

urlpatterns +=patterns('mysite.session_view',

   url(r'^session/post_comment/$','post_comment'),

)

#mysite/session_view.py

def post_comment(request):

   errors=[]

   if request.method == 'POST':

       if not request.POST.get('subject',''):

           errors.append('Enter a subject.')

       if not request.POST.get('message',''):

           errors.append('Enter a meeage.')

       if request.POST.get('email') and '@' not in request.POST['email']:

           errors.append('Enter a valid e-mail address.')

       if request.session.get('has_commented', False):

          return HttpResponse("You've already commented.")

       if not errors:

           #do something here, eg: save it to database

           request.session['has_commented'] = True

           return HttpResponse('Thanks for your comment!')

   return render_to_response('post_comment.html',\

                              {'errors':errors,},\

                             context_instance=RequestContext(request))

 

#mysite/templates/post_comment.html

<html>

<head>

   <title>post comment</title>

</head>

<body>

   <h1>post comment</h1>

   {% if errors %}

       <ul>

           {% for error in errors %}

           <li>{{ error }}</li>

           {% endfor %}

       </ul>

   {% endif %}

         <formaction="" method="post">

                   {%csrf_token %}

                   <p>Subject:<input type="text" name= "subject"value="{{ subject }}"></p>

                   <p>Youre-mail(optional):<input type="text" name="email"value="{{ email }}">

                   <p>message:<textareaname ="message" rows="10" cols="50">{{ message}}</textarea><p>

                   <inputtype="submit" value="Submit">

        </form>

</body>

</html>

 

登陆视图(但是我们更鼓励使用django提供的验证方法而不是自己完成。后面会讲到验证方法)

def login(request):

   if request.method != 'POST':

       raise Http404('Only POSTs are allowed')

   try:

       m = Member.objects.get(username=request.POST['username'])

       if m.password == request.POST['password']:

            request.session['member_id'] = m.id

           return HttpResponseRedirect('/you-are-logged-in/')

   except Member.DoesNotExist:

       return HttpResponse("Your username and password didn'tmatch.")

下面的例子将是一个在上面已通过`` login()`` 登录的用户:

 

def logout(request):

   try:

       del request.session['member_id']

   except KeyError:

       pass

returnHttpResponse("You're logged out.")

 

### 设置测试是否允许Cookies

 

在访问网页时(get),尝试设置cookie,在登录的时候(post),判断设置cookie是否正常.然后进行分支处理.

 

def login(request):

   errors=[]

   if request.method == 'POST':

       if not request.POST.get('username',''):

           errors.append('Enter a username.')

       if not request.POST.get('password',''):

           errors.append('Enter a password.')

       if not errors:

           ifrequest.session.test_cookie_worked():

               request.session.delete_test_cookie()

                returnHttpResponse("Logged in.")

           else:

                return HttpResponse('Pleaseenable coookie.')

   request.session.set_test_cookie()

   return render_to_response('login.html',\

                             {'errors':errors,}, \

                             context_instance=RequestContext(request))

1)判断是否允许设置cooke:

> request.session.test_cookie_worked()

 

2)删除测试cookie:

> request.session.delete_test_cookie()

 

3)请求的时候设置cookie(正常访问网页时判断)

> request.session.set_test_cookie()

 

## 在视图(View)外使用Session

 

1)需要导入包: fromdjango.contrib.sessions.models import Session

 

2) 常见的函数/属性:exprire_data,session_data,get_decoded()

 

 

Users and Authentication

 

Django 认证/授权 系统会包含以下的部分:

 

>用户 : 在网站注册的人

 

>权限 : 用于标识用户是否可以执行某种操作的二进制(yes/no)标志

 

>组 :一种可以将标记和权限应用于多个用户的常用方法

 

>Messages : 向用户显示队列式的系统消息的常用方法

 

## 打开认证支持

 

1> 需要确认用户使用cookie,这样sesson 框架才能正常使用。1

 

2>将'django.contrib.auth' 放在你的 INSTALLED_APPS 设置中,然后运行 manage.py syncdb以创建对应的数据库表。

 

3>确认 SessionMiddleware 后面的MIDDLEWARE_CLASSES 设置中包含 'django.contrib.auth.middleware.AuthenticationMiddleware'SessionMiddleware

 

### 判断用户是否登录

```python

if request.user.is_authenticated():

    #Do something for authenticated users.

else:

    #Do something for anonymous users.

```

 

##  使用User对象

 

```python

# 设置用户组

myuser.groups = group_list

 

# 给用户添加组

myuser.groups.add(group1, group2,...)

 

# 把用户从组里移除

myuser.groups.remove(group1, group2,...)

 

# 把用户从所有组里移除

myuser.groups.clear()

 

# 用户的权限相关

myuser.permissions = permission_list

myuser.permissions.add(permission1,permission2, ...)

myuser.permissions.remove(permission1,permission2, ...)

myuser.permissions.clear()

```

-----

 

## 登录和退出--自己编写login,logout的视图

 

自己编写login和logout的话:

```python

#mysite/urls.py

urlpatterns +=patterns('mysite.user_login_logout_view',

   url(r'^session/user/login/$','login'),

   url(r'^session/user/logout/$','logout'),                 

)

#mysite/user_login_logout_view.py

from django.contrib import auth

 

def login(request):

   errors=[]

   if request.method == 'POST':

       username = request.POST.get('username', '')

       password = request.POST.get('password', '')

       if not request.POST.get('username',''):

           errors.append('Enter a username.')

       if not request.POST.get('password',''):

           errors.append('Enter a password.')

       if not errors:

           user = auth.authenticate(username=username,password=password)

           if user is not None and user.is_active:

               auth.login(request,user)

                return HttpResponse('You havelogged in.')

           else:

                return HttpResponse('usrname orpassword invalid.')

   return render_to_response('user_login.html',\

                              {'errors':errors,}, \

                             context_instance=RequestContext(request)) 

def logout(request):

   auth.logout(request)

   return HttpResponseRedirect("/session/user/login/")

#mysite/templates/user_login.html

<html>

<head>

   <title>login</title>

</head>

<body>

   <h1>login</h1>

   {% if errors %}

       <ul>

           {% for error in errors %}

           <li>{{ error }}</li>

           {% endfor %}

       </ul>

   {% endif %}

         <formaction="" method="post">

                   {%csrf_token %}

                   <p>username<input type="text" name= "username"value="{{ username }}"></p>

                   <p>password<inputtype="password" name="password" value="{{ password}}">

                   <inputtype="submit" value="Submit">

        </form>

</body>

</html>

```

 

上面自己实现的过程中:

1> 在URLconf里设置了2个url

 

2> 在视图里编写了两个函数来处理登录和登出

 

登录分以下几个步骤:

 

a) 获取用户名和密码

>username = request.POST.get('username','')

 

b) 进行授权验证

>auth.authenticate(username=username,password=password)

 

c) 授权成功,则通过session保存用户状态等信息

> auth.login(request,user)

 

d) 处理登录后才能做的事项.

 

3> 在模版里 ,简单的写了一个表单.

 

##登录和退出--使用系统视图

```python

#mysite/urls.py

from django.contrib.auth.views importlogin,logout

urlpatterns += patterns('',

   url(r'^session/accounts/login/$',login,{'extra_context': {'next':'/hello'}}),

   url(r'^session/accounts/logout/$',logout),                 

)

#mysite/templates/registration/login.html

<html>

<head>

   <title>login</title>

</head>

<body>

   <h1>login</h1>

{% block content %}

 

  {%if form.errors %}

   <p class="error">Sorry, that is not a valid username orpassword</p>

  {%endif %}

 

 <form action="" method="post">

         {%csrf_token %}

   <label for="username">User name:</label>

   <input type="text" name="username"value="" id="username">

   <label for="password">Password:</label>

   <input type="password" name="password"value="" id="password">

 

   <input type="submit" value="login" />

   <input type="hidden" name="next" value="{{next|escape }}" />

 </form>

 

{% endblock %}

</body>

</html>

 

```

1)在上面,我们并没有自己编写login,logout视图,而是

 

通过导入包的形式,使用系统自带的视图.

 

注意:

> 这里我们给login添加了额外的内容

 

> {'extra_context': {'next': '/hello'}}

 

> 与表单的中的next数据对应.(表单中next从这里获得.)

 

2) 表单的路径是"mysite/templates/registration/login.html",需要自己编写login的模版

 

a)模版中需要使用{% csrf_token%}

 

b)有个hidden的next字段

 

3)默认的登陆后跳转是"/accounts/profile",使用next字段重写.这里,我们跳转到hello

 

## 在某一个页面中,判断用户是否已经认证登录--->login_required

 

第一种方法是,使用 request.user.is_authenticated().

 

```python

def login(request):

   ...

           if user is not None and user.is_active:

                auth.login(request,user)

                #return HttpResponse('You havelogged in.')

                returnHttpResponseRedirect('/session/limited_acess_vote/')

           else:

                return HttpResponse('usrname orpassword invalid.')

   return render_to_response('user_login.html',\

                              {'errors':errors,}, \

                             context_instance=RequestContext(request))

 

def vote_view(request):

   if not request.user.is_authenticated():

       return HttpResponse("not authenticated.")

   else:

       return HttpResponse("yes authenticated.")

```

在登录后,跳转到vote_view视图,

 

如果用户已经认证,或者用户没有认证.

 

第二种方法是,使用auth包里的"login_required"修饰符.

```python

from django.contrib.auth.decorators importlogin_required

@login_required(login_url="/session/user/login/")

#function under login_required, will beauthenticate.

# if authentication failed,will return tologin_url.

def poll_view(request):

   return HttpResponse("you are in poll_view")

```

 

定义的类poll_view在

>@login_required(login_url="/session/user/login/")

之后,这样,在这句之后的所有视图都会使用login_required来认证.

 

login_required中,如果认证失败,默认跳转到登录页面,

 

可以通过login_url参数指定.

 

---

 

## 对已经登录用户,进一步限制访问---->user_passes_test

 

可以通过检查用户是否具有某个权限,进一步限制用户访问:

```python

#urls.py

urlpatterns +=patterns('mysite.user_login_logout_view',

   ...

   url(r'^session/limited_acess_vote2/$','vote_view2'),

)

#user_login_logout_view.py

from django.contrib.auth.decorators importuser_passes_test

def user_can_vote(user):

   #return user.is_authenticated() anduser.has_perm("poll.can_vote")

   return user.is_authenticated()

@user_passes_test(user_can_vote,login_url="/session/user/login/")

def vote_view2(request):

   return HttpResponse("vote_view2 under user_passes_test.")

```

访问"session/limited_acess_vote2/"的时候,使用视图"vote_view2"

 

但是,在视图上面,我们使用了修饰符@user_passes_test()

 

这个函数需要一个回调函数,可选的登录url.

 

这样以后,如果访问视图的时候,用户没有通过测试(这里我们测试是user_can_vote(),里面判断用户是否登录,当然,可以判断用户是否具有某某权限,是否在某个组里,等等.),那么跳转到登录界面.

 

 

### 限制用户访问的三个修饰符:login_required,user_passes_test,permission_required

 

总结下功能:

 

* login_required, 只是用户判断用户是否已经登录.

 

* user_passes_test,可以对用户进行各种判断:

 * 是否登录认证(**注意:user_passes_test不会自动检查 User是否认证**)

 * 是否具有某个权限

 * 是否在某个组...

 * 等等

 

* permission_required,可以用来对判断用户是否具有某个权限,例如:

 

 

```python

from django.contrib.auth.decorators importpermission_required

 

@permission_required('polls.can_vote',login_url="/login/")

def vote(request):

    #do vote here.

```

上面的代码,判断用户是否具体有权限"'polls.can_vote".

 

## 限制通用视图的访问-->重新包装视图函数

 

如何限制通用视图的访问呢?

可以使用上面的login_required,**重新包装视图函数**:

 

```python

from django.contrib.auth.decorators import login_required

from django.views.generic.date_based importobject_detail

@login_required

def limited_object_detail(*args, **kwargs):

   return object_detail(*args, **kwargs)

```

 

## 管理 Users, Permissions和 Groups

 

### 创建用户-->User.objects.create_user()

 

```python

>>> fromdjango.contrib.auth.models import User

>>> user =User.objects.create_user(username="faith",email='apple@qq.com',password='faith')

>>> user.is_staff = True

>>> user.save()

>>> 

```

### 修改密码-->user.set_password('xx')

```python

>>> user = User.objects.get(username='faith')

>>> user.set_password('faith')

>>> user.save()

>>> 

```

 

### 用户注册-->

```python

#urls.py

 

urlpatterns +=patterns('mysite.user_login_logout_view',

   ...

   url(r'^session/user/register$','register'),

)

 

#mysite/user_login_logout_view.py

from django import forms

from django.contrib.auth.forms importUserCreationForm

def register(request):

   if request.method == 'POST':

       form = UserCreationForm(request.POST)

       if form.is_valid():

           new_user = form.save()

           return HttpResponseRedirect('/session/user/login/')

   else:

       form = UserCreationForm()

   return render_to_response("registration/register.html", \

                              {'form':form}, \

                              context_instance=RequestContext(request))

#mysite/templates/registration/register.html

{% block content %}

 <h1>Create an account</h1>

 

 <form action="" method="post">

         {%csrf_token %}

     {{ form.as_p }}

     <input type="submit" value="Create theaccount">

 </form>

{% endblock %}

 

```

1) 在urls.py里,指定URLconf

 

2) 在view里register():

 

 *GET:显示表单

 *POST:根据提交值检查表单,如果有效,创建用户,返回登录界面.

 

注意:还是需要使用"RequestContext"

 

3) 编写模版,显示表单

 

注意:表单里,需要{% csrf_token %}.

![register ](https://raw.githubusercontent.com/urmyfaith/NotesOfDjangoBook/master/notes/images/register.gif)

----

 

## 在模版中使用认证数据.

 

> 当前登入的用户以及他(她)的权限可以通过RequestContext 在模板的context中使用

 

```python

#urls.py

   url(r'^session/user/user_data$','user_data_in_templates'),

 

#user_login_logout_view.py

def user_data_in_templates(request):

   return render_to_response("use_data_in_templates.html", \

context_instance=RequestContext(request))

 

#mysite/templates/use_data_in_templates.html

{% if user.is_authenticated %}

 <p>Welcome, <b>{{ user.username }}</b>.Thanks forlogging in.</p>

{% else %}

 <p>Welcome, new user. Please log in.</p>

{% endif %}

```

注意:

 

1) 在view中,需要使用RequestContext

 

2) 在模版中,可以使用user对象,以及对象的各种方法/属性等.

 

## 权限,组和消息--->messages.add_message()

 

> 消息系统会为给定的用户接收消息。 每个消息都和一个 User相关联。

 

接收和显示消息的方法:

 

> 要创建一条新的消息,使用user.message_set.create(message='message_text')

 

> 要获得/删除消息,使用user.get_and_delete_messages() ,

 

> 这会返回一个 Message 对象的列表,并且从队列中删除返回的项。

 

```python

#urls.py

urlpatterns += patterns('mysite.user_message_view',

   url(r'^session/message/playlist/(?P<songs>[\w-]+)/$','create_palylist'),

)

#user_message_view.py

from django.shortcuts importrender_to_response

from django.template import RequestContext

from django.contrib import messages

def create_palylist(request,songs):

    #creat playlist here.

   #request.user.message_set.create(message="Your playlist was addedsuccessfully.")

   messages.add_message(request, messages.INFO, 'Your playlist was addedsuccessfully')

   return render_to_response("user_message.html", \

                             {"songs":songs}, \

                             context_instance=RequestContext(request))

#mysite/tempaltes/user_message.html

{% if messages %}

<ul class="messages">

   {% for message in messages %}

                   <li>{{message }}</li>

   {% endfor %}

</ul>

{% endif %}

 

<p>Your palylist : <strong>{{songs }}</strong> has been created.

 

1) URLcof里接收参数songs

 

2) 视图里,使用messages.add_message()方法来创建一条消息.

 

需要导入包from django.contrib import messages

 

 

3) 在模版里

 

 * 使用RequestContext

 * 传递songs参数供模版使用,**但是不显式提供messages给模版!**

 * 模版里使用for循环来遍历

 

4) **使用messages框架,不需要用户登录.**

 

5) request.user.message_set.creat()方法已经过时.

 

0 0