3

ifttt.comのように機能するプロジェクトを作成しました。

そのために私は を使用しますFormWizard

RSS実際、それはとの 2 つのサービスだけでうまく動作します。Evernote

FormWizard が期待するようにFORMSandを設定できます。これが私のandの平和です。TEMPLATESurls.pyviews.py

urls.py

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

ビュー.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 つの専用 CBV を作成したくありません (想像もできません)。

したがって、まず、次の手順でプロセスを変更する必要があります。

  • 最初のページには、ユーザーが選択できるサービスが表示されます
  • 2 ページ目では、ステップ 1 で選択したサービスから取得したいデータをユーザーに尋ねます。
  • 3 番目のページには、ユーザーがステップ 1 で選択したサービスなしで選択できるサービスが表示されます。
  • 4 ページ目では、(システムが取得する) データの移動先 (ステップ 3 で選択したサービス内) をユーザーに尋ねます。
  • 5 ページ目 (および最後のページ) には、トリガーに名前を付けるための説明フィールドが表示されます。

与える具体的な例で:

  • ページ 1 Twitter を選択
  • ページ 2 タイムラインからデータを取得することを選択
  • ページ 3 私は Facebook を選びます
  • page 4 壁にデータを置くことにしました
  • 5ページに「これが私のTwitterからFacebookへの引き金です」と書きました;)

したがって、このプロセスでは、FORMS のコンテンツを動的に変更して、前の手順で選択したサービスから FormWizard の名前を入力できるようにする必要があります。TEMPLATES dict についても同じです。

ご覧のとおり、ウィザードの開始時には、どのサービスが選択されるかを事前に知ることができません。これが、動的にデータを入力する必要がある理由ですFORMSTEMPLATES

誰かがこれを行う方法を知っているか、続行する方法を提案できる場合は、感謝します.

よろしく

注意:私はDjango 1.4を使用しています

4

1 に答える 1

5

これが私がそれを処理する方法です

まず、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
  • DummyForm以下で動的に処理される2つの不明なもの(実際には2回)

以下を提供するforms.pyDummyForm

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__get_form_listで定義した関数からデータをロードしますurls.py
  • のと のドロップダウンで選択したサービスから、ステップ 1 と 3get_context_dataの を変更する必要があります。サービスの名前は「FoobarService」なので、「サービス」を分割して、以下のサービスのフォームを呼び出します。DummyFormProviderFormConsummerFormFoobar(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でそれを行うことにしましたが、それはどのステップにも適応できます;)

于 2013-09-25T07:49:08.810 に答える