[英]Django SessionWizardView current step missing from form_list after Ajax request
I've got a SessionWizardView
process with conditional extra steps which at the end of the first step essentially asks 'do you want to add another person' so my condition is generated by checking the cleaned data for the previous step; 我有一个带有条件额外步骤的
SessionWizardView
进程,在第一步结束时基本上要求'你想添加另一个人',所以我的条件是通过检查上一步的清理数据生成的;
def function_factory(prev_step):
""" Creates the functions for the condition dict controlling the additional
entrant steps in the process.
:param prev_step: step in the signup process to check
:type prev_step: unicode
:return: additional_entrant()
:rtype:
"""
def additional_entrant(wizard):
"""
Checks the cleaned_data for the previous step to see if another entrant
needs to be added
"""
# try to get the cleaned data of prev_step
cleaned_data = wizard.get_cleaned_data_for_step(prev_step) or {}
# check if the field ``add_another_person`` was checked.
return cleaned_data.get(u'add_another_person', False)
return additional_entrant
def make_condition_stuff(extra_steps, last_step_before_repeat):
cond_funcs = {}
cond_dict = {}
form_lst = [
(u"main_entrant", EntrantForm),
]
for x in range(last_step_before_repeat, extra_steps):
key1 = u"{}_{}".format(ADDITIONAL_STEP_NAME, x)
if x == 1:
prev_step = u"main_entrant"
else:
prev_step = u"{}_{}".format(ADDITIONAL_STEP_NAME, x-1)
cond_funcs[key1] = function_factory(prev_step)
cond_dict[key1] = cond_funcs[key1]
form_lst.append(
(key1, AdditionalEntrantForm)
)
form_lst.append(
(u"terms", TermsForm)
)
return cond_funcs, cond_dict, form_lst
last_step_before_extras = 1
extra_steps = settings.ADDITIONAL_ENTRANTS
cond_funcs, cond_dict, form_list = make_condition_stuff(
extra_steps,
last_step_before_extras
)
I've also got a dictionary which stores step data behind a key accessible via the session cookie, which also holds a list of the people's details entered by a user. 我还有一个字典,用于存储通过会话cookie访问的密钥后面的步骤数据,该会话cookie还包含用户输入的人员详细信息列表。 After the first form, this list is rendered as a select box & on selection triggers an Ajax call to the
SessionWizard
with kwargs which triggers the call to a method which returns a JsonResponse
; 在第一个表单之后,此列表呈现为一个选择框&on selection触发对带有kwargs的
SessionWizard
的Ajax调用,该kwargs触发对返回JsonResponse
的方法的调用;
class SignupWizard(SessionWizardView):
template_name = 'entrant/wizard_form.html'
form_list = form_list
condition_dict = cond_dict
model = Entrant
main_entrant = None
data_dict = dict()
def get_data(self, source_step, step):
session_data_dict = self.get_session_data_dict()
try:
data = session_data_dict[source_step].copy()
data['event'] = self.current_event.id
for key in data.iterkeys():
if step not in key:
newkey = u'{}-{}'.format(step, key)
data[newkey] = data[key]
del data[key]
except (KeyError, RuntimeError):
data = dict()
data['error'] = (
u'There was a problem retrieving the data you requested. '
u'Please resubmit the form if you would like to try again.'
)
response = JsonResponse(data)
return response
def dispatch(self, request, *args, **kwargs):
response = super(SignupWizard, self).dispatch(
request, *args, **kwargs
)
if 'get_data' in kwargs:
data_id = kwargs['get_data']
step = kwargs['step']
response = self.get_data(data_id, step)
# update the response (e.g. adding cookies)
self.storage.update_response(response)
return response
def process_step(self, form):
form_data = self.get_form_step_data(form)
current_step = self.storage.current_step or ''
session_data_dict = self.get_session_data_dict()
if current_step in session_data_dict:
# Always replace the existing data for a step.
session_data_dict.pop(current_step)
if not isinstance(form, TermsForm):
entrant_data = dict()
fields_to_remove = [
'email', 'confirm_email', 'password',
'confirm_password', 'csrfmiddlewaretoken'
]
for k, v in form_data.iteritems():
entrant_data[k] = v
for field in fields_to_remove:
if '{}-{}'.format(current_step, field) in entrant_data:
entrant_data.pop('{}-{}'.format(current_step, field))
if '{}'.format(field) in entrant_data:
entrant_data.pop('{}'.format(field))
for k in entrant_data.iterkeys():
new_key = re.sub('{}-'.format(current_step), u'', k)
entrant_data[new_key] = entrant_data.pop(k)
session_data_dict[current_step] = entrant_data
done = False
for i, data in enumerate(session_data_dict['data_list']):
if data[0] == current_step:
session_data_dict['data_list'][i] = (
current_step, u'{} {}'.format(
entrant_data['first_name'],
entrant_data['last_name']
)
)
done = True
if not done:
session_data_dict['data_list'].append(
(
current_step, u'{} {}'.format(
entrant_data['first_name'],
entrant_data['last_name']
)
)
)
return form_data
If you step through the form without triggering the Ajax call then the form submits and the condition dict behaves as expected. 如果您在不触发Ajax调用的情况下单步执行表单,则表单将提交,条件dict将按预期运行。 But if the Ajax is triggered and the data is returned to the form, once you submit the form the session data appears to have gone.
但是,如果触发Ajax并将数据返回到表单,则一旦提交表单,会话数据就会消失。 Is there a way to change the way I've got this setup so that
get_data()
can return the data to the page, without destroying the session? 有没有办法改变我的设置方式,以便
get_data()
可以将数据返回到页面,而不会破坏会话?
I've got the SESSION_ENGINE
set to cached_db
on a dev server but I've got an issue whereby when you submit the first conditional form and the system calls get_next_step()
followed by get_form_list()
and the condition check no longer returns that first conditional form so I'm left with my default form list and a ValueError
raised because current_step
is no longer part of form_list
. 我已经在开发服务器
cached_db
SESSION_ENGINE
设置为cached_db
但是我遇到了一个问题,即当您提交第一个条件表单并且系统调用get_next_step()
后跟get_next_step()
get_form_list()
并且条件检查不再返回第一个条件因为current_step
不再是form_list
一部分,所以我留下了我的默认表单列表并引发了ValueError
。
So, to recap, I step through my first form, trigger the first conditional form using the 'add_another_person' field which renders the form as expected at which point form_list
looks like this; 因此,回顾一下,我逐步浏览我的第一个表单,使用'add_another_person'字段触发第一个条件表单,该字段按预期呈现表单,此时
form_list
如下所示;
form_list
u'main_entrant' <class 'online_entry.forms.EntrantForm'>
u'additional_entrant_1' <class 'online_entry.forms.EntrantForm'>
u'terms' <class 'online_entry.forms.TermsForm'>
But as soon as additional_entrant_1
triggers the Ajax method, then is submitted, the form_list
runs through the condition dict & looks like this; 但是一旦
additional_entrant_1
触发Ajax方法,然后提交, form_list
运行条件dict并且看起来像这样;
form_list
u'main_entrant' <class 'online_entry.forms.EntrantForm'>
u'terms' <class 'online_entry.forms.TermsForm'>
Could this be an issue with the session storage or the session becoming invalid? 这可能是会话存储或会话变为无效的问题吗?
I always overlook the simple explanation. 我总是忽略这个简单的解释。
The get()
request of the SessionWizardView
resets the storage, and the Ajax call I was making hit the view as a get request, resetting the storage, but also passing back my information. SessionWizardView
的get()
请求重置存储,我正在制作的Ajax调用作为get请求命中视图,重置存储,但也传回我的信息。
So with a simple override of the get()
method I've resolved this; 因此,通过简单覆盖
get()
方法,我已经解决了这个问题;
def get(self, request, *args, **kwargs):
if 'get_data' in kwargs:
data_id = kwargs['get_data']
step = kwargs['step']
response = self.get_data(data_id, step)
else:
self.storage.reset()
# reset the current step to the first step.
self.storage.current_step = self.steps.first
response = self.render(self.get_form())
return response
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.