2016-07-04 8 views
1

私はタスクを表すdjangoモデルを持っています。このタスクは 'DRAFT'から 'COMPLETION'までの複数の状態を経て、その間にさまざまなフィールドがユーザーの入力を要求することから明示的に拒否することに変わります。たとえば、タスクが完了している間に、そのタスクが完了した日付を変更することはできません。また、状態に基づいてページに異なるリンクを表示したい場合(つまり、チェックしている場合、[このタスクを完了]と言う送信ボタンが必要です)Djangoフォーム内の状態/条件付きのフィールドを処理する方法

元は、ハードコーディングを超えた方法ではうまくいかず、これらのモデルに何らかの価値がもたらされ、代わりに明示的なリストが選択されました。 (ここでより良いアプローチがあれば分かるだろう)。

私が持っているキーの問題は、これらのフィールドとその状態を管理する方法です。 {%if task.status = 'ACCEPTED'%}のようなテンプレートに条件文を入れるのが最も簡単なようですが、それは非常に多くのビジネスロジックをテンプレートに入れているようです。私はまた、すでにテンプレートに入っているとフィールドを無効にするということは、フォームよりもはるかに難しいという印象を受けます。

私の現在のアプローチは、これらの状態を管理するためにビューを使用することですが、それは面倒であり、テンプレートのリンク名などを変更する方法を(私にとっては)解決しません。

if task.status = Task.ACCEPTED: 
    form.fields['datereceived'].disabled = True 
if task.status = Task.COMPLETED: 
    ... 

は、これらを管理するための図であって、テンプレートをオーバーロードすることなく、これらを管理するdjangonic /もっとニシキヘビありますか?

サンプルコードので、言い訳のバグ:

モデル

class Task(models.Model): 
    STATUS_CHOICES = (
     (DRAFT,  DRAFT), 
     (ALLOCATED, ALLOCATED), 
     (ACCEPTED, ACCEPTED), 
     (CHECKING, CHECKING), 
     (COMPLETED, COMPLETED), 
     (WITHDRAWN, WITHDRAWN), 
     (ON_HOLD, ON_HOLD), 
    ) 

    status = models.CharField(max_length=20, choices=STATUS_CHOICES,default=DRAFT) 
    datereceived = models.DateField(blank=True, null=True) 
    dateworked = models.DateField(blank=True, null=True) 
    datechecked = models.DateField(blank=True, null=True) 
    datecompleted = models.DateField(blank=True, null=True) 
    datedue = models.DateField(blank=True, null=True) 

のModelForm

class TaskForm(forms.ModelForm): 
    class Meta: 
    model = Task 
    #fields = All fields listed individually but hard to pick out for sample 
    widgets = { 
     'datereceived': forms.DateInput(attrs={'class':'datepicker'}), 
     'datedue': forms.DateInput(attrs={'class':'datepicker'}), 
     'datecompleted': forms.DateInput(attrs={'class':'datepicker'}), 
    } 

答えて

1

ように、フォームのインスタンス化コードのロジックを入れてみてください:

class TaskForm(forms.ModelForm): 
    class Meta: 
     model = Task 

    def handle_state(self, *args, **kwargs): 
     task = getattr(self, 'instance', None) 
     if task:  
      if task.status = Task.ACCEPTED: 
       self.fields['datereceived'].disabled = True 
      elif task.status = Task.COMPLETED: 
       ... 

    def __init__(self, *args, **kwargs): 
     super(TaskForm, self).__init__(*args, **kwargs) 
     self.handle_state(*args, **kwargs)  
+0

興味深い。私はクラスがdjangoでどのように動作するかについてあまり明確ではありません...私は現在、以下のコードを実行します - フォームが正常に完了すると、フォームページにリダイレクトされます。これは、これが起こったときに状態を変更することができますか?(つまり、ステータス=受付 - フォームの変更の意味は完了しました、タスクインスタンスが保存されました - 再発行されたフォームは異なるフィールドを表示しません) if taskno: context ['task'] = get_object_or_404 (Task、pk = taskno) form = TaskForm(request.POSTまたはNone、instance = context ['task']) – Ewanw

+0

@Ewanwはい、うまくいくはずです。それがどうなるか教えてください。 –

+0

@YarathROCKこれまでのところ、とても良いです。 http://stackoverflow.com/questions/38235623/avoiding-fresh-instantiation-of-modelform-fields-in-djangoによると、私はフォーム管理に苦しんでいます。私は、状態を制御する(つまり、正しい状態のために右のボタンに表示する)よりも多くのテンプレート操作を必要としていますが、やむを得ないことだと思います。 – Ewanw

関連する問題