python - 动态表单向导

标签 python django evernote

我做了一个类似 ifttt.com 的项目

为此,我使用 FormWizard

实际上,只有 RSSEvernote

这两个服务可以正常工作

我可以像 FormWizard 预期的那样设置 FORMSTEMPLATES,这是我的 urls.py View .py :

urls.py

# wizard
url(r'^service/create/$', UserServiceWizard.as_view([RssForm, EvernoteForm,
     ServicesDescriptionForm]), name='create_service'),

views.py

from th_rss.forms import RssForm
from th_evernote.forms import EvernoteForm
from django_th.forms.base import ServicesDescriptionForm

FORMS = [("rss", RssForm),
     ("evernote", EvernoteForm),
     ("services", ServicesDescriptionForm), ]

TEMPLATES = {
    '0': 'rss/wz-rss-form.html',
    '1': 'evernote/wz-evernote-form.html',
    '2': 'services_wizard/wz-description.html'}


class UserServiceWizard(SessionWizardView):
    instance = None

    def get_form_instance(self, step):

        if self.instance is None:
            self.instance = TriggerService()
        return self.instance

    def done(self, form_list, **kwargs):
        trigger = self.instance
        trigger.provider = UserService.objects.get(
            name='ServiceRss',
            user=self.request.user)
        trigger.consummer = UserService.objects.get(name='ServiceEvernote',
                            user=self.request.user)
        trigger.user = self.request.user
        trigger.status = True
        # save the trigger
        trigger.save()
            #...then create the related services from the wizard
        for form in form_list:
            if form.cleaned_data['my_form_is'] == 'rss':
            from th_rss.models import Rss
            Rss.objects.create(
                name=form.cleaned_data['name'],
                url=form.cleaned_data['url'],
                status=1,
                trigger=trigger)
            if form.cleaned_data['my_form_is'] == 'evernote':
                from th_evernote.models import Evernote
            Evernote.objects.create(
                tag=form.cleaned_data['tag'],
                notebook=form.cleaned_data['notebook'],
                status=1,
                trigger=trigger)

        return HttpResponseRedirect('/')

    def get_template_names(self):
        return [TEMPLATES[self.steps.current]]

但实际上该项目只处理 2 项服务,我不想(也无法想象)为每一对新服务(如 TwitterEvernoteWizard、RssTwitterWizard、FacebookTwitterWizard 等)创建一个专用的 CBV。

所以首先,我必须按这些步骤更改流程:

  • 第一页显示用户可以选择的服务
  • 第二页询问用户他想从第 1 步选择的服务中获取哪些数据
  • 第 3 页显示用户可以选择的服务,而无需在第 1 步中选择服务
  • 第 4 页询问用户(系统将抓取的)数据将去往何处(在第 3 步选择的服务中)
  • 第 5 个(也是最后一个)页面显示用于命名触发器的描述字段。

用一个具体的例子给出:

  • 第 1 页我选择 Twitter
  • 第2页我选择从时间线抓取数据
  • 第 3 页我选择 Facebook
  • 第4页我选择把资料上墙
  • 第 5 页我输入“这是我从 Twitter 到 Facebook 的触发器”;)

因此,在这个过程中,我需要能够动态更改 FORMS 的内容,以使用我之前选择的服务中的 FormWizard 名称填充它。 TEMPLATES 字典也一样。

如您所见,在向导开始时,我无法提前知道将选择哪个服务。 这就是为什么我需要动态填充 FORMSTEMPLATES

如果有人知道如何执行此操作或可以建议一种继续进行的方法,我将不胜感激。

问候

注意:我使用的是 Django 1.4

最佳答案

我是这样处理的

首先,urls.py:

url(r'^service/create/$','django_th.views.get_form_list', name='create_service'),

然后在 views.py 中:

我做到了:

def get_form_list(request, form_list=None):
    if form_list is None:
        form_list = [ProviderForm, DummyForm, ConsummerForm, DummyForm, \
                     ServicesDescriptionForm]
    return UserServiceWizard.as_view(form_list=form_list)(request)

这允许定义 5 个步骤:

  • 3 个已知表单(ProviderFormConsummerFormServicesDescriptionForm
  • 2 个未知的(DummyForm 实际上是两次)将在下面动态处理

提供 DummyFormforms.py :

class DummyForm(forms.Form):
    pass

下一步就是从ProviderForm中获取数据,从中获取我选择的服务,加载这个选择服务的for:

在我的 views.py 中:

class UserServiceWizard(SessionWizardView):

    def __init__(self, **kwargs):
        self.form_list = kwargs.pop('form_list')
        return super(UserServiceWizard, self).__init__(**kwargs)

    def get_form_instance(self, step):
        if self.instance is None:
            self.instance = UserService()
        return self.instance

    def get_context_data(self, form, **kwargs):
        data = self.get_cleaned_data_for_step(self.get_prev_step(
                                                    self.steps.current))
        if self.steps.current == '1':
            service_name = str(data['provider']).split('Service')[1]
            #services are named th_<service>
            #call of the dedicated <service>ProviderForm
            form = class_for_name('th_' + service_name.lower() + '.forms',
                  service_name + 'ProviderForm')
       elif self.steps.current == '3':
            service_name = str(data['consummer']).split('Service')[1]
            #services are named th_<service>
            #call of the dedicated <service>ConsummerForm
            form = class_for_name('th_' + service_name.lower() + '.forms',
                  service_name + 'ConsummerForm')
        context = super(UserServiceWizard, self).get_context_data(form=form,
                                  **kwargs)
    return context

这里:

  • __init__ 从我在 urls.py
  • 中定义的 get_form_list 函数加载数据
  • get_context_data 中,我需要从我在 ProviderForm消费者表格。由于该服务名为“FoobarService”,我拆分“服务”以调用服务 Foobar(Consummer|Provider)Formclass_for_name() 下面的形式:

class_for_name :

def class_for_name(module_name, class_name):
   m = importlib.import_module(module_name)
   c = getattr(m, class_name)
   return c

最后:

有了所有这些,我就可以在任何步骤动态地动态更改表单,事实上,我决定在步骤 1 和 3 中执行此操作,但可以针对任何步骤进行调整;)

关于python - 动态表单向导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18836547/

相关文章:

python - 为什么我使用 "sudo"关键字后,权限被拒绝?

python - 瀑布图python?

python - 使用 Python 更新 Evernote 笔记

django - 覆盖 Django 中的 brabeion 模板路径

java - 我们可以从evernote文件中提取文本内容吗

ios - 我正在使用uiwebview中加载的内容可编辑html。隐藏/显示键盘时,我需要代码来设置光标位置

python - 如何对齐 TreeView odoo中的字段?

python - Python : Handling requests exceptions the right way

python - 检查 F 对象的结果是否大于零

python - 在 Django 中使用交互式控件制作 Bokeh 图