在django测试中设置会话变量 [英] Setting a session variable in django tests

查看:111
本文介绍了在django测试中设置会话变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个工作

  def test_access_to_home_with_location(self):
self.client.login(username = self.user .get_username(),password ='pass')
session = self.client.session
session ['location'] = [42]
session.save()
响应= self.client.get(reverse('home'))

但这个

  def test_access_to_home_with_location(self):
session = self.client.session
session ['location'] = [42]
session.save()
response = self.client.get(reverse('home'))

分开

  =============== ================================================== === 
错误:test_access_to_home_with_location(posts.tests.HomeViewTestCase)
----------------------------- -----------------------------------------
追溯(最近的电话最后):
文件tests.py,第32行,在test_access_to_home_with_location
session.save()
AttributeError:'dict'对象没有属性'save'

所以似乎在调用 self.client.login() self.client.session 只是一个空字典。有没有办法将其初始化为会话对象?

解决方案

当客户端中没有设置cookie时, session 属性是一个空的dict,因此你的错误。以下是 django.test.client.Client的相关来源

 
获取当前会话变量

如果设置中为'django.contrib.sessions'.INSTALLED_APPS:
engine = import_module(settings.SESSION_ENGINE)
cookie = self.cookies.get(settings.SESSION_COOKIE_NAME,None)
如果cookie:
返回engine.SessionStore(cookie.value)
return {}
session = property(_session)

由于您没有登录找不到与 settings.SESSION_COOKIE_NAME 匹配的密钥的Cookie。



但是,您可以手动创建一个会话对象,如下所示:

 如果不是self.client.session:
engine = import_module(settings.SESSION_ENGINE)

self.client.session = engine.SessionStore()
self.client.session.save ()

这是登录的方式 客户端中的处理程序创建一个新的会话。



编辑:我意识到你也需要保存会话键入一个cookie,以便下一个请求使用相同的会话



这是一个帮助函数,你可以放在你的客户端创建新会话和引用cookie的子类:

  def set_session_data(self,key,value) :
无论身份验证设置会话数据的快捷方式

如果不是self.client.session:
#在数据库中保存新会话并添加Cookie引用它

engine = import_module(settings.SESSION_ENGINE)

self.client.session = engine.SessionStore()
self.client.session.save()

session_cookie = settings.SESSION_COOKIE_NAME
self.client.cookies [session_cookie] = self.client.session.session_key
cookie_data = {
'max-age':无,
'path': '/',
'domain':settings.SESSION_COOKIE_DOMAIN,
'secure':settings.SESSION_COOKIE_SECURE或None,
'expires':None,
}
self .client.cookies [session_cookie] .update(cookie_data)

self.client.session [key] = value
self.client.session.save()

注意:我不是说这是唯一的方法,这是我通过阅读发现的一种方式django源代码。此答案中的代码未经测试/运行,因此可能需要进行微调。



进一步阅读



要了解 SessionStore 的工作原理,您可以查看 django.contrib.sessions 模块。 / p>

要了解如何处理客户端中的会话和Cookie,您可以查看 django。 test.client.Client


This works

def test_access_to_home_with_location(self):
    self.client.login(username=self.user.get_username(), password='pass')
    session = self.client.session
    session['location'] = [42]
    session.save()
    response = self.client.get(reverse('home'))

But this

def test_access_to_home_with_location(self):
    session = self.client.session
    session['location'] = [42]
    session.save()
    response = self.client.get(reverse('home'))

breaks with

====================================================================== 
ERROR: test_access_to_home_with_location (posts.tests.HomeViewTestCase)       
----------------------------------------------------------------------      
Traceback (most recent call last):                                            
  File "tests.py", line 32, in test_access_to_home_with_location                            
    session.save()                                                              
AttributeError: 'dict' object has no attribute 'save'

So it seems with out calling self.client.login() self.client.session is just an empty dictionary. Is there a way to initialize it as a session object?

解决方案

When no cookies are set in the client the session property is a empty dict, hence your error. Here is the relevant source of django.test.client.Client:

def _session(self):
    """
    Obtains the current session variables.
    """
    if 'django.contrib.sessions' in settings.INSTALLED_APPS:
        engine = import_module(settings.SESSION_ENGINE)
        cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
        if cookie:
            return engine.SessionStore(cookie.value)
    return {}
session = property(_session)

Since you are not logged in the cookie with the key matching settings.SESSION_COOKIE_NAME is not found.

However you could manually create a session object like this:

if not self.client.session:
    engine = import_module(settings.SESSION_ENGINE)

    self.client.session = engine.SessionStore()
    self.client.session.save()

This is the way the login handler in Client creates a new session.

EDIT: I realized you also need to save the session key in a cookie so that the next request uses the same session

Here's a helper function you could put in your Client sub class that creates a new session and a referencing cookie:

def set_session_data(self, key, value):
    """Shortcut for setting session data regardless of being authenticated"""

    if not self.client.session:
        # Save new session in database and add cookie referencing it

        engine = import_module(settings.SESSION_ENGINE)

        self.client.session = engine.SessionStore()
        self.client.session.save()

        session_cookie = settings.SESSION_COOKIE_NAME
        self.client.cookies[session_cookie] = self.client.session.session_key
        cookie_data = {
            'max-age': None,
            'path': '/',
            'domain': settings.SESSION_COOKIE_DOMAIN,
            'secure': settings.SESSION_COOKIE_SECURE or None,
            'expires': None,
        }
        self.client.cookies[session_cookie].update(cookie_data)

    self.client.session[key] = value
    self.client.session.save()

Note: I'm not saying this is the only way to do this, this is one way I found out by reading the django source code. The code in this answer is not tested/run, therefor it might need some fine tuning.

Further reading

To read about how SessionStore works you can look at the django.contrib.sessions module.

To read about how session and cookies are handled in Client you can look at django.test.client.Client.

这篇关于在django测试中设置会话变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆