会话密钥不会从Flask测试中修改 [英] Session key is not modified from Flask tests

查看:178
本文介绍了会话密钥不会从Flask测试中修改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的Flask应用程序构建一个测试,在其中一个测试中需要修改一个会话密钥(本身就是一个值列表),然后检查应用程序的行为是否被修改过的密钥内容。我正在使用 Flask文档用于从测试中修改 session



这里是摘录的示例代码,用于演示问题报表,以及在测试期间打印的内容):
$ b

my_app.py

 来自烧瓶导入(
烧瓶,
烧录,


app = Flask(__ name__)
app.secret_key ='坏密钥'

@ app.route('/ create_list /',methods = ['POST'])
def create_list ():
session ['list'] = ['1','2']
returnList created!
$ b $ app_route('/ in_list /')
def in_list():
print(str(session ['list']))#['1', '2'],但是为什么?
如果在session ['list']中输入'3':
return'session ['list'] contains'3'!
else
returnOy vey!3不在会话中['list']

test_my_app.py

  import烧瓶

from unittest import TestCase
import my_app
$ b $ class TestApp(TestCase):
$ b $ def setUp(self):
self.test_client = my_app.app.test_client()
self.test_client.post('/ create_list /')

def testAppendList(self):
with self.test_client作为客户:
with client.session_transaction()as sess:
sess ['list']。append('3')
print(str(sess ['list']))# ['1','2','3'],如预期的那样
response = client.get('/ in_list /')
expected_response =session ['list'] contains'3'! .encode('ascii')
self.assertTrue(expected_response == response.data)

我的问题是:


  1. 为什么是t他发生了什么?

  2. 从测试中修改 session ['list'] 的正确方法是什么? b


解决方案


  1. As 这个答案,以及 doc flask.session 修改属性提及:




如果会话对象检测到修改,则为true。请注意,对可变结构的修改不会自动拾取,在这种情况下,您必须自己将该属性显式设置为True。

所以,问题1的答案是:它发生是因为list是一个可变结构,因此它在会话中的修改不会自动拾取。


  1. 修改可变结构的正确方法(从测试中不要紧)是将 session.modified 设置为真正完成更改后。

因此,修改了 test_my_app.py

导入烧瓶

  from unittest import TestCase 
import my_app
$ b $ class TestApp(TestCase):
$ b $ def setUp(self):
self.test_client = my_app.app.test_client()
self.test_client.post('/ create_list /')

def testAppendList(self):
with se lf.test_client作为客户端:
with client.session_transaction()as sess:
sess ['list']。append('3')
sess.modified = True
response encode('ascii')
self.assertTrue(expected_response == response)= client.get('/ in_list /')
expected_response =session ['list'] contains'3'!数据)






以下是我发现的一些情况你可能也会这么做)有趣的是,我在这个问题中偶然发现了这个问题:
$ b


  1. (非常明显):Mutables是如果赋值和修改发生在同一个上下文中,那就修改它。

所以,就像这样:

  @ app.route('/ create /')
def create():
session ['example'] = ['one', 'two']
session ['example']。append('three')
session ['example']。remove('one')
return s tr(session ['example'])

返回 ['two' ,'three']


  1. 与原始问题一样,函数的修改将完成(这可能是相当误导)。

请考虑以下内容:

  @ app.route('/ create /')
def create():
session ['example'] = ['one' ,'two']
return str(session ['example'])

@ app.route('/ modify /')
def modify():
'session''example']。append('four')
return str(session ['example'])

@ app.route('/ display /')
def display():
return str(session ['example'])

现在,运行应用程序并访问以下网址:

  ... / create /#['one','two'] 
... / modify /#['one','two','four']
... / display /#['one ','two']仍然是




  1. ,当你在函数的结尾调用 render_template(),以及模板的外观取决于会话中的mutable时,会非常困惑。在这种情况下, session 被从当前上下文传递到模板中,这与前面的例子非常相似。

假设我们有:
$ b $ p my_app.py


$ b $

  @ app.route('/ create /')
def create():
session ['example'] = ['one','two']
return str(session ['example'])

@ app.route('/ modify /')
def modify() :
session ['example']。append('four')
return render_template('my_template.html')

@ app.route('/ display /')
def display():
return str(session ['example'])

my_template.html
$ b

 <!doctype html> 
< html>
< head>< title>显示会话['example']< / title>< / head>
< body>
< div>
{%if session ['example']%}
{{session ['example']}}
{%else%}
session ['example'] is not set =(
{%endif%}
< / div>
< / body>
< / html>



一旦我们打电话:

  .. ./create/#['one','two'] 
... / modify /#会呈现包含['one','two','four']
...的页面/ display /#though,still ['one','two']


I am building a tests for my Flask application, in one of the test there is a need to modify a session key (which itself is a list of values), and then check that app behaviour is altered by the modified key content. I'm using an approach from Flask documentation for modifying session from tests.

Here is an excerpt example code, to demonstrate the problem (I have added print statements, along with what they are printing during test run):

my_app.py

from flask import (
Flask,
session,
)

app = Flask(__name__)
app.secret_key = 'bad secret key'

@app.route('/create_list/', methods=['POST'])
def create_list():
    session['list'] = ['1', '2']
    return "List created!"

@app.route('/in_list/')
def in_list():
    print(str(session['list'])) # ['1', '2'], but why?
    if '3' in session['list']:
        return "session['list'] contains '3'!"
    else:
        return "Oy vey! '3' is not in the session['list']"

test_my_app.py

import flask

from unittest import TestCase
import my_app

class TestApp(TestCase):

def setUp(self):
    self.test_client = my_app.app.test_client()
    self.test_client.post('/create_list/')

def testAppendList(self):
    with self.test_client as client:
        with client.session_transaction() as sess:
            sess['list'].append('3')
        print(str(sess['list'])) # ['1', '2', '3'], as expected
        response = client.get('/in_list/')
        expected_response = "session['list'] contains '3'!".encode('ascii')
        self.assertTrue(expected_response == response.data)

My questions are:

  1. Why is this happening?
  2. What is the proper way to modify session['list'] from tests?

解决方案

  1. As this answer, as well as doc on flask.session modified attribute mention:

True if the session object detected a modification. Be advised that modifications on mutable structures are not picked up automatically, in that situation you have to explicitly set the attribute to True yourself.

So, the answer to question 1 is: it happens because list is a mutable structure and thus it's modification in session is not picked up automatically.

  1. The proper way to modify mutable structure (it doesn't matter from tests or not) is to set session.modified to True after change was done.

So, revised code for test_my_app.py would look like this:

import flask

from unittest import TestCase
import my_app

class TestApp(TestCase):

def setUp(self):
    self.test_client = my_app.app.test_client()
    self.test_client.post('/create_list/')

def testAppendList(self):
    with self.test_client as client:
        with client.session_transaction() as sess:
            sess['list'].append('3')
            sess.modified = True
        response = client.get('/in_list/')
        expected_response = "session['list'] contains '3'!".encode('ascii')
        self.assertTrue(expected_response == response.data)


Here are some cases I have found (and you might as well) interesting, which I've stumbled upon during digging around this problem:

  1. (pretty obvious one): Mutables are modified if assignment and modification happens in the same context.

So, something like this:

@app.route('/create/')
def create():
    session['example'] = ['one', 'two']
    session['example'].append('three')
    session['example'].remove('one')
    return str(session['example'])

Will return ['two', 'three']

  1. Like in the original question, in the context of modifying function the modification will be done (which could be quite misleading).

Consider the following:

@app.route('/create/')
def create():
    session['example'] = ['one', 'two']
    return str(session['example'])

@app.route('/modify/')
def modify():
    session['example'].append('four')
    return str(session['example'])

@app.route('/display/')
def display():
    return str(session['example'])

Now, running the app and accessing the following urls:

.../create/ # ['one', 'two']
.../modify/ # ['one', 'two', 'four']
.../display/ # ['one', 'two'] still

  1. Another case, that is quite confusing is when you calling render_template() at the end of your function, and appearance of the template depending on the mutable in session. In such case session is being passed into the template from current context, which is quite similar to the previous case.

Assume we have:

my_app.py

@app.route('/create/')
def create():
    session['example'] = ['one', 'two']
    return str(session['example'])

@app.route('/modify/')
def modify():
    session['example'].append('four')
    return render_template('my_template.html')

@app.route('/display/')
def display():
    return str(session['example'])

my_template.html

<!doctype html>
<html>
    <head><title>Display session['example']</title></head>
    <body>
        <div>
            {% if session['example'] %}
                {{ session['example'] }}
            {% else %}
                session['example'] is not set =(
            {% endif %}
        </div>
    </body>
</html>

Once we'll call:

.../create/ # ['one', 'two']
.../modify/ # will render page containing ['one', 'two', 'four']
.../display/ # though, still ['one', 'two']

这篇关于会话密钥不会从Flask测试中修改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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