0

処理ジョブを管理する Django アプリがあり、ユーザー フレンドリーなプロセス リクエスト フォームを作成しようとしています。基本的に、プロセスを定義する Process モデルがあり、関連する ProcessInput モデルが入力パラメーターを定義します。これら 2 つのモデルをミラーリングして Process の「インスタンス」を作成するのが、ProcessRequest および ProcessRequestInputValue モデルです。

ここでの要件は、新しい ProcessRequest には、すべての ProcessInput に一致する ProcessRequestInputValue の完全なセットが存在する必要があるということです。現在、inlineformset_factory を使用して、すべての入力値を同時に入力できるプロセス要求を送信するためのフォームを作成しています。また、入力の選択肢を事前設定するための初期データも提供しました。これは機能していますが、ModelChoiceField であるため、ユーザーは入力値のカテゴリを変更できます。この値を「修正」して、基本的に読み取り専用のテキストウィジェットであるテキストとして表示したいと思います。

関連するコードは次のとおりです。まず、モデル:

class Process(models.Model):
    process_name = models.CharField(unique=True)

class ProcessInput(models.Model):
    process = models.ForeignKey(Process)
    input_name = models.CharField()
    default_value = models.CharField(null=True, blank=True, max_length=1024)

    class Meta:
        unique_together = (('process', 'input_name'),)

class ProcessRequest(models.Model):
    process = models.ForeignKey(Process)
    request_user = models.ForeignKey(User, editable=False)

class ProcessRequestInputValue(models.Model):
    process_request = models.ForeignKey(ProcessRequest)
    process_input = models.ForeignKey(ProcessInput)
    value = models.CharField(null=False, blank=False, max_length=1024)

    class Meta:
        unique_together = (('process_request', 'process_input'),)

フォームは次のとおりです。

class ProcessRequestForm(ModelForm):
    class Meta:
        model = ProcessRequest
        exclude = ('process', 'request_user')

class ProcessRequestInputValueForm(ModelForm):
    class Meta:
        model = ProcessRequestInputValue
        exclude = ('process_request',)

最後に、フォームセットのビューのコード:

PRInputValueFormSet = inlineformset_factory(
    ProcessRequest,
    ProcessRequestInputValue,
    form=ProcessRequestInputValueForm,
    extra=process.processinput_set.count(),
    can_delete=False,
)

form = ProcessRequestForm(instance=process_request)

initial_data = list()

for process_input in process.processinput_set.all():
    initial_data.append({'process_input': process_input})

formset = PRInputValueFormSet(
    instance=process_request,
    initial=initial_data)

これは機能し、フォームエラーに関するすべての記入済み情報を保持します。ただし、上で述べたように、フォームは ModelChoiceField であるため、プロセス入力をドロップダウンとして表示します。

たとえば、"Add Numbers" というプロセスがあり、"NumberA" と "NumberB" という 2 つの入力があるとします。これは、フォームセットを使用した ProcessRequest フォームからのスクリーン グラブです。

ここに画像の説明を入力

基本的に、選択肢を値のラベルとして表示したいと思います。いくつかのアプローチを試しましたが、うまく機能するものは見つかりませんでした。何か案は?

4

3 に答える 3

0

ハックのように思えますが、これまでに見つけた唯一の解決策は、ダミーのフォーム フィールドを作成してラベル値を格納することです。以下は私がこれまでに持っているコードです。

私はこれに満足していません。他の解決策を見たいと思っています。

フォーム.py:

class ProcessRequestForm(ModelForm):
    class Meta:
        model = ProcessRequest
        exclude = ('process', 'request_user')


class ProcessRequestInputValueForm(ModelForm):
    value_label = forms.CharField(widget=forms.HiddenInput())
    process_input = forms.ModelChoiceField(
        queryset=ProcessInput.objects.all(),
        widget=forms.HiddenInput())

    class Meta:
        model = ProcessRequestInputValue
        exclude = ('process_request',)

ビュー.py:

def create_process_request(request, process_id):
    process = get_object_or_404(Process, pk=process_id)
    process_request = ProcessRequest(process=process, request_user=request.user)

    PRInputValueFormSet = inlineformset_factory(
        ProcessRequest,
        ProcessRequestInputValue,
        form=ProcessRequestInputValueForm,
        extra=process.processinput_set.count(),
        can_delete=False,
    )

    if request.method == 'POST':
        # validate the form / formset and save
    else:
        form = ProcessRequestForm(instance=process_request)
        initial_data = list()

        for process_input in process.processinput_set.all():
            # note 'value_label' is used for the 'value' field's label
            initial_data.append(
                {
                    'process_input': process_input,
                    'value_label': process_input.input_name
                })

        formset = PRInputValueFormSet(instance=process_request, initial=initial_data)

    return render_to_response(
        'create_process_request.html',
        {
            'process': process,
            'form': form,
            'formset': formset,
        },
        context_instance=RequestContext(request)
    )

テンプレート:

Process: {{ process.process_name }}<br/>

<form action="{% url 'create_process_request' process.id %}" method="post">
  {% csrf_token %}

  {{ form.non_field_errors }}
  {{ formset.management_form }}
  <Inputs: <br/>

    {% for input_form in formset %}
      {% for hidden_field in input_form.hidden_fields %}

        {% if hidden_field.name == 'process_input' %}
          {{ hidden_field.as_hidden }}
        {% elif hidden_field.name == 'value_label' %}

          {# Needed if form submission has errors, else our custom label goes away #}
          {# Could be used to "hack" our custom label on POST %}
          {{ hidden_field.as_hidden }}

          {# Our custom dynamic label #}
          {{ hidden_field.value }}

        {% endif %}
      {% endfor %}

      {{ input_form.value }}

      {% if input_form.value.errors %}
        {{ input_form.value.errors|striptags }}
      {% endif %}

      <hr/>

    {% endfor %}
      <button type="submit">Save</button>
    </div>
  </div>
</form>

そして、はるかに使いやすいフォーム:

ここに画像の説明を入力

于 2013-08-13T21:05:43.863 に答える