python – 动态FormWizard
作者:互联网
我做了一个像ifttt.com一样的项目.
为此,我使用FormWizard.
实际上,只有RSS和Evernote这两项服务才能正常工作
我可以设置FormWizard所期望的FORMS和TEMPLATES,这是我的urls.py和views.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.
首先,我将不得不通过以下步骤更改流程:
>第一页显示用户可以选择的服务
>第2页询问用户在步骤1中从选择的服务中获取哪些数据
>第3页显示用户可以选择的服务,而无需选择un step1
>第4页询问用户数据(系统将抓取)的位置(在步骤3的选择服务中)
>第5页(和最后一页)显示描述字段以命名触发器.
以concret为例,它将给出:
>第1页我选择Twitter
>第2页我选择从时间线中获取数据
>第3页我选择Facebook
>第4页我选择将数据放在墙上
>第5页我把“这是我从Twitter到facebook的触发器”;)
因此,通过这个过程,我需要能够动态地更改FORMS的内容,并使用我之前选择的服务中的FormWizard名称填充它.
同样适用于TEMPLATES dict.
正如您所看到的,在向导的开始时,我无法预先知道将选择哪个服务.
这就是我需要动态填充FORMS和TEMPLATES的原因
如果有人知道如何做到这一点或者只是建议一种方法继续下去,我将不胜感激.
问候
注意:我使用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知识表单(ProviderForm,ConsummerForm,ServicesDescriptionForm
> 2个未知的(事实上两次DummyForm)将在下面动态处理
提供DummyForm的forms.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和ConsummerForm的下拉列表中选择的服务中更改步骤1和3中的DummyForm.由于该服务名为’FoobarService’,我将“服务”拆分为使用下面的class_for_name()调用服务Foobar(Consummer | Provider)表单的形式:
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步执行此操作但是可以适用于任何步骤;)
标签:evernote,python,django 来源: https://codeday.me/bug/20191002/1841873.html