2017-03-05 47 views
0

我遇到了以下視圖和表單的問題。然而,當我編輯任何不保存的字段時,表單會正確加載。經過一些調試後,我認爲這是由於以下兩點之一:request.method == "POST"正在評估爲false,或者form.is_valid()正在評估爲false。因此,我的模板或我的clean()方法可能有問題嗎?我搜索了以前的問題,找不到任何有用的東西。我也檢查了我的clean()方法對Django文檔,並認爲它是確定的。使用Django表單POST方法的問題

views.py

@login_required 
def edit_transaction(request, pk): 
    transaction = get_object_or_404(Transaction, pk=pk) 
    if request.method == "POST": 
     form = TransactionForm(request.POST, instance=transaction) 
     if form.is_valid(): 
      transaction = form.save(commit=False) 
      transaction.updated = timezone.now() 
      transaction.save() 
      return redirect('view_transaction_detail', pk=transaction.pk) 
    else: 
     form = TransactionForm(request=request, instance=transaction) 
    return render(request, 'budget/new_transaction.html', {'form': form}) 

forms.py

class TransactionForm(forms.ModelForm): 

    class Meta: 
     model = Transaction 
     fields = ('title', 'transaction_type', 'category', 'budgeted_amount', 'actual_amount', 'date', 'comments',) 

    #new_category field to allow you to add a new category 
    new_category = forms.CharField(max_length=30, required=False, label="New Category Title") 

    def __init__(self, request, *args, **kwargs): 
     super(TransactionForm, self).__init__(*args, **kwargs) 
     #category is now not a required field because you will use category OR new_category 
     self.fields['category'].required=False 
     #set to allow use of self.request.user to set user for category 
     self.request = request 

    def clean(self):  
     category = self.cleaned_data.get('category') 
     new_category = self.cleaned_data.get('new_category') 
     if not category and not new_category: 
      # raise an error if neither a category is selected nor a new category is entered 
      raise forms.ValidationError('Category or New category field is required') 
     elif not category: 
      # create category from new_category 
      category, created = Category.objects.get_or_create(title=new_category, defaults={'user': self.request.user}) 
      self.cleaned_data['category'] = category 

     return super(TransactionForm, self).clean() 

模板

{% extends 'budget/base.html' %} 

{% block content %} 

    <h2>New transaction</h2> 
    <h4>To add a new category, leave Category blank and enter your new category in the New Category Title field</h4> 
    <form method="POST" class="post-form"> 
     {% csrf_token %} 
     {{ form.as_p }} 
     <button type="submit" class="save btn btn-default">Save</button> 
    </form> 

{% endblock %} 

更新後的答案 - 通過kwargs

def __init__(self, *args, **kwargs): 
    super(TransactionForm, self).__init__(*args, **kwargs) 
    self.fields['category'].required=False 
    self.request = kwargs.pop('request', None) 

回答

1

正如我對你的最後一個問題提到的,因爲你已經改變了形式的init方法的簽名,你需要傳遞請求實例化它既次訪問請求。只有當它不是POST時你才這樣做;所以,當它是一個POST時,Python會獲取您傳遞的數據並將其分配給request參數,從而使數據本身保持空白。

form = TransactionForm(request, data=request.POST, instance=transaction) 

請注意,正是因爲這個原因,改變簽名是一個壞主意;相反,通過request作爲關鍵字參數,並在該方法從kwargs得到它。

+0

謝謝,這是有道理的。我可以檢查我對你最近的評論的理解嗎?你的意思是沿着我作爲更新發布的內容(對不起,它不會在評論框中使用縮進格式正確格式化)? – pasta1020

+0

只是補充一點,修改後的代碼確實有效。 – pasta1020