2014-03-13 26 views
0

總體目標:能夠更新和創建來自同一網頁的多個對象的記錄。當用戶更新或創建一條記錄時,他們會被引導回同一頁面。當他們回到此頁面時,他們的帖子結果應該被反映出來,並且他們應該能夠安全刷新頁面而無需重新提交表單。Django ModelForm - 具有不同動作視圖和重定向的模板中的多個表單

這裏是我的views.py

@login_required() 
def index(request): 
    activity_model_form = ActivityModelForm() 
    rhi_model_form = RhiModelForm() 
    activity_list = Activity.objects.all() 
    rhi_list = Rhi.objects.all() 

    if request.method == 'POST': 
     context = { 
      'activity_list': activity_list, 
      'rhi_list': rhi_list, 
     } 
     return render(request, 'ec/index.html', context) 
    else: 
     context = { 
      'activity_list': activity_list, 
      'rhi_list': rhi_list, 
      'activity_model_form': activity_model_form, 
      'rhi_model_form': rhi_model_form, 
     } 
    return render(request, 'ec/index.html', context) 

def add_activity(request): 
    if request.method == 'POST': 
     aForm = ActivityModelForm(request.POST) 
     if aForm.is_valid(): 
      aForm.save() 
    return HttpResponseRedirect(reverse('ec:index')) 

def add_rhi(request): 
    if request.method == 'POST': 
     rForm = RhiModelForm(request.POST) 
     if rForm.is_valid(): 
      newRhi = rForm.save() 
    return HttpResponseRedirect('ec:index') 

forms.py

class RhiModelForm(forms.ModelForm): 
    class Meta: 
     model = Rhi 

class ActivityModelForm(forms.ModelForm): 
    class Meta: 
     model = Activity 

模板(的index.html)

{% for activity in activity_list %} 
     {{activity}} 
    {% endfor %} 
    <br> 
    {% for rhi in rhi_list %} 
     {{rhi}} 
    {% endfor %} 
    <br> 
    <form aciton="{% url 'ec:add_rhi' %}" method="post"> 
     {% csrf_token %} 
     {{ rhi_model_form }} 
     <input type="submit" value="Add"/> 
    </form> 
    <br> 
    <form action="{% url 'ec:add_activity' %}" method="post"> 
     {% csrf_token %} 
     {{ activity_model_form }} 
     <input type="submit" value="Add" /> 
    </form> 

urls.py

urlpatterns = patterns('', 
      url(r'^$', views.index, name='index'), 
      url(r'^forms/add_activity',views.add_activity, name='add_activity'), 
      url(r'^forms/add_rhi',views.add_rhi,name='add_rhi'), 
) 

頁的index.html是應該持有幾種形式的主頁。在這種情況下,我決定使用它們提供的所有內置功能的模型表單。看看這裏的其他類似帖子,似乎創建不同的視圖來處理這些表單是首選的方式。從那裏,我想重新加載index.html,但我想重新查詢數據庫以獲取更新/新創建的記錄。

兩個問題:

1)模型視圖不保存。試圖提交rhi_model_form時,我被重定向到index.html而沒有記錄保存。對於我在這裏發佈的內容,我做了newRhi = rForm.save(),但我也嘗試過rForm.save(),但沒有看到任何效果。爲什麼有些示例將save方法設置爲變量?爲什麼這有幫助?無論如何,目前這兩種情況都不適合我。

2)提交後,呈現索引視圖,但它通過if request.method =='POST'部分的代碼。它爲什麼這樣做?如果我刷新頁面,它希望重新提交表單。如何在提交所有需要的數據後加載此頁面並使其刷新以避免重新提交?

回答

1

好的 - 我能弄清楚這個代碼應該如何重構。對於誰是要把它讓用戶可以在同一頁面上提交不同型號不同的形式,而不是用在頁面刷新討厭重新提交打擾其他新手,這裏是一般結構如下:

  1. 模板:把每個模型形式的模板,但要確保動作的屬性點不同的意見
  2. 的URLconf:在你的urls.py在表單動作標籤
  3. 查看每個視圖正確的URL映射:創建視圖總數等於該等式:1 + n。其中n =您想要處理的表單數量,「1」表示您的實際頁面。爲放入模板中的每個表單創建一個單獨的視圖。在這些「n」個視圖的每個視圖中,使用您在文檔中看到的所有標準內容(即request.method == 'post'yourform.is_valid())。但關鍵在於,在處理表單後,您需要使用redirect('view:name')!如果你只是想硬編碼視圖,我相信你可以做redirect('/view/name/')。使用該重定向功能,系統不傳遞任何數據回主頁面視圖它調用(即「1」從上面。)

views.py

@login_required() 
def index(request): 
    rhi_model_form = RhiModelForm() 
    activity_model_form = ActivityModelForm() 
    rhi_list = Rhi.objects.all() 
    activity_list = Activity.objects.all() 
    context = { 
     'rhi_model_form': rhi_model_form, 
     'rhi_list': rhi_list, 
     'activity_model_form': activity_model_form, 
     'activity_list': activity_list, 
    } 
    return render(request, 'ec/index.html', context) 

@login_required() 
def add_rhi(request): 
    if request.method == 'POST': 
     rForm = RhiModelForm(request.POST) 
     if rForm.is_valid(): 
      rForm.save() 
      return redirect('ec:index') 
     else: 
      rhi_errors = rForm.errors 
      rhi_model_form = RhiModelForm() 
      context = { 
       'rhi_errors': rhi_errors, 
       'rhi_model_form': rhi_model_form, 
      } 
      return render(request, 'ec/index.html', context) 

@login_required() 
def add_activity(request): 
    if request.method == 'POST': 
     aForm = ActivityModelForm(request.POST) 
     if aForm.is_valid(): 
      activity = aForm.save(commit=False) 
      activity.lastModifiedBy = request.user 
      activity.createdBy = request.user 
      activity.save() 
      return redirect('ec:index') 
     else: 
      activity_errors = aForm.errors 
      activity_model_form = ActivityModelForm() 
      context = { 
       'activity_errors': activity_errors, 
       'activity_model_form': activity_model_form, 
      } 
      return render(request, 'ec/index.html', context) 

形式的.py

class RhiModelForm(forms.ModelForm): 
    class Meta: 
     model = Rhi 
     exclude = ['slug'] 

class ActivityModelForm(forms.ModelForm): 
    class Meta: 
     model = Activity 
     exclude = ['createdBy','lastModifiedBy'] 

模板(在我的情況 - 的index.html)

{% if rhi_model_form %} 
    {% if error_message %}<p><strong>{{error_message}}</strong></p>{% endif %} 
    {% if rhi_errors %}{{ rhi_errors }} {% endif %} 

    <form action="{% url 'ec:add_rhi' %}" method="post"> 
     {% csrf_token %} 
     {{ rhi_model_form }} 
     <input type="submit" value="Add RHI"/> 
    </form> 
    {% endif %} 

    {% if activity_model_form %} 
    {% if error_message %}<p><strong>{{error_message}}</strong></p>{% endif %} 
    {% if activity_errors %}{{ activity_errors }} {% endif %} 
    <form action="{% url 'ec:add_activity' %}" method="post"> 
     {% csrf_token %} 
     {{ activity_model_form.non_field_errors }} 
     {{ activity_model_form }} 
     <input type="submit" value="Add Activity"/> 
    </form> 
    {% endif %} 

總結 - 核心概念要牢記是:

  • POST:除非你想改變服務器上的東西,不要使用此方法。基本上,在任何視圖中都不包含任何包含,檢查等「POST」的代碼,除非該視圖本身會處理來自用戶的數據。在這個例子中,這就是爲什麼你在索引視圖中看不到任何關於「POST」的原因。
  • 重定向/渲染:這兩個快捷鍵是關鍵。重定向會將代碼流發送到其參數中引用的視圖,並且不會傳遞上下文。就我而言,這正是我想要的。渲染不會將視圖作爲參數,而應該用於將數據「裝運」出來,在這種情況下應該用於模板。
  • 備註:在模板中,我將每個表單都包裝在「if」控件中,因爲如果當前存在表單提交錯誤,我不想爲最終用戶顯示不同的表單的「提交」按鈕表格正在提交。 (由於表單的動作調用了不同的視圖,並且因爲我沒有在其視圖中通過驗證而重新加載失敗的表單)。
相關問題