从URL模式或发布数据中将初始数据插入到SessionWizardView表单字段中?
我已经在这个问题上耗尽了我的资源,所以我必须向社区提交一个问题。从URL模式或发布数据中将初始数据插入到SessionWizardView表单字段中?
场景:
在我的urls.py文件我有这样一个规律:
url(r'^entry_form/(?P<sheet_id>\d+)/', SheetWizard.as_view([Sheet1,Sheet2,Sheet3])),
当用户访问像 “127.0.0.1/myapp/entry_form/77” 我想一个url让Django呈现Sheet1,但最初输入的值为“77”。
初论:
我forms.py文件看起来类似于:
class Sheet1(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(Sheet1, self).__init__(*args, **kwargs)
#create a helper object
self.helper = FormHelper(self)
#dont render the form tags
self.helper.form_tag = False
#Make a nice layout
self.helper.layout = Layout(
TabHolder(
Tab(
'Sheet Information', #Tab name text
PrependedText('sheet_field', 'Django-'), #The field with prepended text
)
)
#Now set the initial value of the field to sheet_id from url pattern
self.fields['sheet_field'].initial = str(sheet_id)+'-'+ str(time()).replace('.','_')
#??? Not sure where to get sheet_id from???
通知的最后一行有一个变量命名为“sheet_id”,这应该是值“77”,从URL来由用户输入的模式。
问题:
到目前为止,我不确定如何从我的forms.py或views.py文件的URL模式访问值“sheet_id”。由于这是一个基于类的观点,我不能简单地创建关键字“sheet_id =无”,又名这样的事情是行不通的:
class SheetWizard(SessionWizardView, sheet_id=None):
#this breaks
我已经能够得到一些数据views.py使用request.GET 和一个类似“127.0.0.1/myapp/entry_form/?sheet_id=77”的网址,但我不知道如何将其转换为SessionWizardView用户会话的第一种形式。
如果有人能帮助我,我将不胜感激。 并感谢你的所有善良智慧!
使用向导的dispatch
方法:
def dispatch(self, request, *args, **kwargs):
self.sheet_id = kwargs.get('sheet_id', None)
return super(SheetWizard, self).dispatch(request, *args, **kwargs)
然后使用self.sheet_id
内get_form_initial
方法来填充初始值的形式。
感谢mariodev指引我在正确的方向。
我发现这个代码组合为我的应用程序工作:
[urls.py]
url(r'^entry_form/(?P<sheet_id_initial>\d+)/', SheetWizard.as_view([Sheet1,Sheet2,Sheet3])),
[views.py]
class SheetWizard(SessionWizardView):
#some code here
def dispatch(self, request, *args, **kwargs):
self.sheet_id_initial = kwargs.get('sheet_id_initial', None)
return super(SheetWizard, self).dispatch(request, *args, **kwargs)
def get_form_initial(self, step):
initial = self.initial_dict.get(step, {})
if int(step) == 0:
initial.update({ 'sheet_id_initial': self.sheet_id_initial })
return initial
[forms.py]
class Sheet1(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(Sheet1, self).__init__(*args, **kwargs)
#create a helper object
self.helper = FormHelper(self)
#dont render the form tags
self.helper.form_tag = False
#Make a nice layout
self.helper.layout = Layout(
TabHolder(
Tab(
'Sheet Information', #Tab name text
PrependedText('sheet_field', 'Django-'), #The field with prepended text
)
)
#finally lets set the initial values
if 'initial'in kwargs:
initial = kwargs.pop('initial')
print initial
if 'sheet_id_initial' in initial:
sheet_id_initial = initial.pop('sheet_id_initial')
#this is where the value from sheet_id_initial is initialized in the field :)
self.fields['sheet_id_initial'].initial = str(sheet_id_initial)+'-'+ str(time()).replace('.','_')
但是,这个母鹿创造一个新问题。我现在可以访问第一个表单,并且按照预期在表单字段中添加了sheet_id_initial中的值,但是当按下submit按钮时,由于POST没有将sheet_id_initial部分添加到请求网址。
[返回首页]
“” “”
没有发现页(404) 请求方法:POST 请求URL:在first_project.urls定义http://192.ip.address.1:8001/sheets/entry_form/
使用URL配置,Django的按以下顺序尝试这些URL模式:
^admin/
^Users/
^sheets/ ^entry_form/(?P<sheet_id_initial>\d+)/
当前URL,sheets/en try_form /,不匹配任何这些。
你看到这个错误,因为你的Django设置文件中有DEBUG = True。将其改为False,Django将显示一个标准的404页面。
“”“”
[附加信息]
要改变从中从任一个URL模式或POST数据达到sheet_id可变的方式是相当直截了当:
第一变化在urls.py正则表达式模式到一个简单的匹配,如:
urlpatterns = patterns('',
url(r'^entry_form/', SheetWizard.as_view([Sheet1,Sheet2,Sheet3])),
#url(r'^entry_form/(?P<sheet_id_initial>\d+)/', SheetWizard.as_view([Sheet1,Sheet2,Sheet3])), #'sheet_id_initial' would be picked up by "self.sheet_id_initial = kwargs.get('sheet_id_initial', None)" in SheetWizard.dispatch()
然后在views.py改变分配在调度重写方法如下所示:
class SheetWizard(SessionWizardView):
def dispatch(self, request, *args, **kwargs):
#self.sheet_id = kwargs.get('sheet_id_initial', None) #used to grab sheet_id_initial from url pattern
if self.request.GET.has_key('sheet_id_initial'):
self.sheet_id_initial = self.request.GET['sheet_id_initial'] #used to grab sheet_id_initial from QueryDict
return super(SheetWizard, self).dispatch(request, *args, **kwargs)
最后,如果你得到MultiValueDictKeyError,我添加了一个try-except块来get_form_initial(),对于从如果POST数据存在调度方法声明的变量的存在测试(但我不能确定这是否是处理最好的办法..)
所以在views.py添加这些行get_form_initial():
class SheetWizard(SessionWizardView):
def get_form_initial(self, step):
initial = self.initial_dict.get(step, {})
if step == "0":
try:
self.sheet_id_initial #check for variable existence
#if we get past this line then the variable existed and we can update initial data
initial.update({ 'sheet_id_initial': self.sheet_id_initial })
except:
#variable didn't exist so lets just move on..
pass
return initial
[更新 - 最好的解决到目前为止]
这个会话向导和基于类的视图可能有点棘手。我发现以前的这两种方法都有某种缺陷,并且意识到我过于复杂化了一些。 但大多数以前的代码是必不可少的,但不是POST或URL模式,我将POST数据存储在会话中,并通过不同URL上的表单访问它!
现在我有一个用户从开始的形式在说地址:具有形式两个领域 “http://192.ip.address.1:8001/sheets/start/”:“part_id_initial”和“sheet_id_initial”
时提交按下用户被重定向到:“http://192.ip.address.1:8001/sheets/entry_form/” 但是,POST数据无法通过重定向进行HTTP限制。
所以你可以保存会话POST数据并通过修改,像这样上面的代码中使用的另一种形式:
urls.py
url(r'^start/', 'process_forms.views.GetStarted'),
url(r'^entry_form/', SheetWizard.as_view([Sheet1,Sheet2,Sheet3])),
意见。py
def GetStarted(request):
form = gettingStarted(request.POST or None)
if request.method == 'POST':
if form.is_valid():
data = form.cleaned_data
request.session['_old_post'] = request.POST #Store POST to be passed to SheetWizard
return redirect('/sheets/entry_form/')
return render_to_response('get_started.html',
locals(),
context_instance=RequestContext(request))
class SheetWizard(SessionWizardView):
def dispatch(self, request, *args, **kwargs):
old_post = request.session.get('_old_post') #Retrieve old POST data to set initial values on session form
if old_post.has_key('sheet_id_initial') and old_post.has_key('part_id_initial'):
self.sheet_id_initial = old_post['sheet_id_initial'] #used to grab sheet_id from QueryDict
self.part_id_initial = old_post['part_id_initial'] #used to grab sheet_id from QueryDict
return super(SheetWizard, self).dispatch(request, *args, **kwargs)
其余的几乎和上面一样。 将POST数据保存到会话中是迄今为止我发现的最干净和最优雅的修复。
希望这有助于!