我在这个问题上的资源非常耗尽,所以我必须向社区提交一个问题。
情景:
在我的urls.py文件中,我有一个类似的模式:
url(r'^entry_form/(?P<sheet_id>\d+)/', SheetWizard.as_view([Sheet1,Sheet2,Sheet3])),
当用户访问类似&#34; 127.0.0.1/myapp/entry_form/77"的网址时;我想让Django渲染Sheet1,但其中一个字段的值为&#34; 77&#34;最初进入。
初论:
我的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???
注意最后一行有一个名为&#34; sheet_id&#34;的变量,它应该是值&#34; 77&#34;来自用户输入的网址格式。
问题:
到目前为止,我不确定如何访问值&#34; sheet_id&#34;来自我的forms.py或views.py文件中的url模式。由于这是一个基于类的视图,我不能简单地创建关键字&#34; sheet_id = None&#34;,也就是说这样的东西不起作用:
class SheetWizard(SessionWizardView, sheet_id=None):
#this breaks
我已经能够使用request.GET将一些数据输入到views.py中 和#34; 127.0.0.1/myapp/entry_form/?sheet_id = 77&#34;但我不知道如何将其传递到SessionWizardView用户会话的第一种形式。
如果有人能帮助我,我将不胜感激。 谢谢你所有的善意!
答案 0 :(得分:1)
使用向导的dispatch
方法:
def dispatch(self, request, *args, **kwargs):
self.sheet_id = kwargs.get('sheet_id', None)
return super(SheetWizard, self).dispatch(request, *args, **kwargs)
然后在get_form_initial
方法中使用self.sheet_id
来填充表单的初始值。
答案 1 :(得分:1)
感谢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('.','_')
然而,这确实会产生一个新问题。我现在可以访问第一个表单,并且url模式中的sheet_id_initial的值已按预期添加到表单字段中,但是当按下提交按钮时,由于POST没有将sheet_id_initial部分添加到请求网址。
[返回页面]
“” “”
找不到页面(404) 请求方法:POST 请求网址:http://192.ip.address.1:8001/sheets/entry_form/
使用first_project.urls中定义的URLconf,Django按以下顺序尝试了这些URL模式:
^admin/
^Users/
^sheets/ ^entry_form/(?P<sheet_id_initial>\d+)/
当前网址sheet / entry_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,我向get_form_initial()添加了一个try-except块,用于测试是否存在从调度方法声明的变量,如果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/” 但是HTTP的限制是POST数据不能与重定向一起使用。
所以你可以通过修改上面的代码来保存会话POST数据并以另一种形式使用它:
urls.py
url(r'^start/', 'process_forms.views.GetStarted'),
url(r'^entry_form/', SheetWizard.as_view([Sheet1,Sheet2,Sheet3])),
views.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数据保存到会话中是最干净的,也是迄今为止我发现的最优雅的解决方案。
希望这有帮助!!