2013-09-16 4 views
1

Я сделал проект, который работает как ifttt.com.Dynamic FormWizard

Для этого я использую FormWizard.

На самом деле, это работает отлично с только 2 услуг, которые RSS и Evernote

Я мог бы установить 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 и так далее.

Итак, прежде всего, мне придется изменить процесс этих шагов:

  • 1-й страницы отображается список служб, пользователь может выбрать
  • второй страницы просит пользователь, что DATAS он хочет, чтобы захватить от выбранного сервиса на шаге 1
  • Третья страница отображает услуги, которые пользователь может выбрать без одного выбранного un step1
  • 4-ая страница просит пользователя, в котором данные (которые система будет захватывать) пойдет (в выбранной службе на этапе 3)
  • На пятой (и последней странице) отображается поле описания для названия триггера.

С Concret Exemple, что даст:

  • страница 1 Я выбираю Twitter
  • стр.2 Я выбираю, чтобы захватить данные сроки
  • страница 3 Я выбираю Facebook
  • страница 4 Я хочу разместить данные на стене
  • страница 5 Я положил «Вот мой спусковой крючок от твиттера к facebook»;)

Итак, с этим процессом мне нужно иметь возможность динамически изменять содержимое FORMS, чтобы заполнить его именем FormWizard из Сервиса, который я выбрал на один шаг раньше. То же самое для TEMPLATES dict.

Как вы можете видеть, в начале Мастера я не могу заранее знать, какая служба будет выбрана. Вот почему мне нужно заполнить dynamicallly FORMS и TEMPLATES

Если кто-нибудь знает, как это сделать, или может просто предложить способ продолжить, я буду признателен.

рассматривает

уведомление: Я использую Django 1.4

ответ

3

вот как я закончил, чтобы справиться с этим

первый, 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 knowns формы (ProviderForm, ConsummerForm,
  • 2 малоизвестные (DummyForm дважды на самом деле), что будет обрабатываться динамически ниже

forms.py который обеспечивает DummyForm:

class DummyForm(forms.Form): 
    pass 

следующий шаг, чтобы получить данные из ProviderForm, получить услугу я выбрал из него, и загрузите для этого выбранной услуги:

в моем 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__ загрузки данных из get_form_list функции я определил в urls.py
  • в get_context_data мне нужно изменить DummyForm на шаге 1 и 3 из службы я выбрал в раскрывающемся меню из ProviderForm и ConsummerForm. Поскольку услуга называется 'FoobarService', я разделил 'Service', чтобы сделать вызов формы службы Foobar(Consummer|Provider)Form с class_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, но это может быть адаптировано для любого шага;)

Смежные вопросы