1

在这个主题上我已经用尽了我的资源,所以我必须向社区提交一个问题。

设想:

在我的 urls.py 文件中,我有一个类似的模式:

url(r'^entry_form/(?P<sheet_id>\d+)/', SheetWizard.as_view([Sheet1,Sheet2,Sheet3])),

当用户访问像“127.0.0.1/myapp/entry_form/77”这样的网址时,我试图让 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”的变量,它应该是来自用户输入的 url 模式的值“77”。

问题:

到目前为止,我不确定如何从 forms.py 或 views.py 文件中的 url 模式访问值“sheet_id”。由于这是一个基于类的视图,我不能简单地创建关键字“sheet_id=None”,也就是这样的东西不起作用:

class SheetWizard(SessionWizardView, sheet_id=None):
    #this breaks

我已经能够使用 request.GET 和诸如“127.0.0.1/myapp/entry_form/?sheet_id=77”之类的 url 将一些数据获取到 views.py 中,但我不知道如何将其通过管道传输到 SessionWizardView 的第一种形式中用户会话。

如果有人可以帮助我,将不胜感激。感谢您的智慧!

4

2 回答 2

1

感谢 mariodev 为我指明了正确的方向。

我发现这种代码组合适用于我的应用程序:

[urls.py]

url(r'^entry_form/(?P<sheet_id_initial>\d+)/', SheetWizard.as_view([Sheet1,Sheet2,Sheet3])), 

[视图.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

[表格.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 请求 URL: 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+)/

当前 URL 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

[更新 - 迄今为止最好的修复]

这个 sessionwizard 和基于类的视图可能有点棘手。我发现这两种以前的方法都以某种方式存在一些缺陷,并意识到我把事情复杂化了一点。但是之前的大部分代码都是必不可少的,但我将 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 数据并以另一种形式使用它:

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

希望这可以帮助!!

于 2014-11-09T17:44:12.807 回答
1

使用向导的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_idinsideget_form_initial方法填充表单的初始值。

于 2014-11-09T07:51:54.427 回答