从URL模式或发布数据中将初始数据插入到SessionWizardView表单字段中?

从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_idget_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数据保存到会话中是迄今为止我发现的最干净和最优雅的修复。

希望这有助于!