Django表单POST方法的问题

时间:2017-03-05 12:55:11

标签: python django forms

我遇到以下视图和表单的问题。表单正确加载,但是当我编辑任何不保存的字段时。经过一些调试后,我认为这是由于以下两种情况之一:request.method == "POST"评估为false,或form.is_valid()评估为false。我的模板或clean()方法可能有问题吗?我搜索过以前的问题,找不到任何有用的东西。我还检查了我的clean()方法对Django文档并认为它没问题。

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 个答案:

答案 0 :(得分:1)

正如我在上一个问题中所提到的,由于您已经更改了表单初始化方法的签名,因此您需要将两次的请求传递给实例化它。你不是在POST时才这样做的;因此,当它是POST时,Python会获取您传递的数据并将其分配给request参数,从而使数据本身为空白。

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

注意正是因为这个原因,改变签名是个坏主意;相反,将request作为关键字参数传递,并在方法内部从kwargs获取。