在一个Django视图上获取“这个QueryDict实例是不可变的”,而不是在另一个视图上

时间:2022-02-05 19:41:10

I have two views, one that is working fine when I try to add to the POST data when a form is not valid, another that gives me a "This QueryDict instance is immutable" error when trying to do the same thing. I know these views are too similar to exist in the first place and plan on combining them... but would like to first understand what is the difference that makes one of them fail.

我有两个视图,一个可以正常工作,当一个表单无效时,当我尝试添加到POST数据时,另一个视图给我一个“这个QueryDict实例是不可变的”错误,当尝试做同样的事情时。我知道这些观点太相似了,根本不存在,我打算把它们结合起来……但是首先我想知道是什么让他们中的一个失败。

This view works fine:

这个视图工作正常:

@login_required
def url_parse(request):
    cu = request.user
    if request.method == 'POST':
        form = UrlBragForm(request.POST, request.FILES)
        if form.is_valid():
            t = handle_image_upload(form.cleaned_data['image'],cu.pk,'url')
            if t:
                b = Brag()
                b.user = cu
                b.image = t
                b.url = form.cleaned_data['url']
                b.description = form.cleaned_data['brag']
                b.active = True
                b.timestamp = time.time()
                b.save()
                tags = parse_tags(form.cleaned_data['brag'])
                if tags:
                    for tg in tags:
                        b.tags.add(tg)
            else:
                errors = form._errors.setdefault("image", ErrorList())
                errors.append(u"There was an issue with your image.  Please try again.")
        else:
            clean = cleanMessage(request.POST['brag'])
            if clean != 'is_clean':
                request.POST['brag'] = clean
    else:
        form = UrlBragForm()
    return render_to_response('brag/url_brag.html', {'form':form,}, context_instance=RequestContext(request))

But this view gives me a "This QueryDict instance is immutable" when trying to fill the request.POST['brag'] with the 'clean' data when view is not valid:

但是这个视图在尝试填充请求时给了我一个“这个QueryDict实例是不可变的”。当视图无效时,使用“clean”数据发布['brag']:

@login_required
def brag_add_image(request):
    cu = request.user
    if request.method == 'POST':
        form = ImageAddBragForm(request.POST, request.FILES)
        if form.is_valid():
            t = handle_image_upload(form.cleaned_data['image'],cu.pk,'url')
            if t:
                b = Brag()
                b.user = cu
                b.image = t
                b.description = form.cleaned_data['brag']
                b.active = True
                b.timestamp = time.time()
                b.save()
                b.url = 'http://%s%s' % (Site.objects.get_current().domain, reverse('image_display', args=(b.pk,)))
                b.save()
                tags = parse_tags(form.cleaned_data['brag'])
                if tags:
                    for tg in tags:
                        b.tags.add(tg)
            else:
                errors = form._errors.setdefault("image", ErrorList())
                errors.append(u"There was an issue with your image.  Please try again.")
        else:
            clean = cleanMessage(request.POST['brag'])
            if clean != 'is_clean':
                request.POST['brag'] = clean
    else:
        form = ImageAddBragForm()
    return render_to_response('brag/image_brag_add.html', {'form':form,}, context_instance=RequestContext(request))

Here is the traceback that was asked for:

以下是被要求提供的回溯数据:

Traceback:
File "site/src/django/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "site/src/django/django/contrib/auth/decorators.py" in _wrapped_view
  20.                 return view_func(request, *args, **kwargs)
File "site/brag/views.py" in brag_add_image
  241.                 request.POST['brag'] = clean
File "site/src/django/django/http/__init__.py" in __setitem__
  439.         self._assert_mutable()
File "site/src/django/django/http/__init__.py" in _assert_mutable
  436.             raise AttributeError("This QueryDict instance is immutable")

Exception Type: AttributeError at /brag/brag_add_image/
Exception Value: This QueryDict instance is immutable

1 个解决方案

#1


2  

Figured it out. It is because of the way I was calling the form in the template. If you change your enctype to multipart you no longer get the error. This in no way is a fix, and you should look at doing this in your form class not a view. But I wanted to figure out why it worked one way and not another.

算出来。这是因为我在模板中调用表单的方式。如果您将enctype更改为multipart,您将不再获得错误。这绝不是一种修复,您应该在表单类而不是视图中进行此操作。但我想弄明白为什么它是用一种方式而不是另一种方式工作的。

<form action="." method="post" class="genForm" enctype="multipart/form-data">

vs

vs

<form action="." method="post" class="genForm">

This seems like it could be a bug in Django (why not enforce in both cases?)

这似乎是Django中的一个bug(为什么不在这两种情况下执行呢?)

Since there seems to be some confusion with this answer I here is a simpler example that shows the same out come:

由于这个答案似乎有些混乱,我这里有一个简单的例子来说明同样的结果:

View :

观点:

def testit(request):
    if request.method == "POST":
        form = testForm(request.POST, request.FILES)
        clean = 'Going to stuff post data with this string'
        if form.is_valid():
            print 'valid'
            request.POST['testOne'] = clean
        else:
            print 'not valid'
            request.POST['testOne'] = clean
    else:
        form = testForm()
    return render_to_response('brag_board/test.html', {'form':form}, context_instance=RequestContext(request))

Form:

形式:

class testForm(forms.Form):
    testOne = forms.CharField(required=True)
    testTwo = forms.CharField(required=True)

Template that gives a error:

出现错误的模板:

<!DOCTYPE html>
<html>
<head>
    <title>test</title>
</head>
<body>

<form action="." method="post" class="genForm">
{{ form }}
{% csrf_token %}
<button type="submit" name="action" value="addnewsletter">test</button>
</form>

</body>
</html>

Template that does not give an error:

没有错误的模板:

<!DOCTYPE html>
<html>
<head>
    <title>test</title>
</head>
<body>

<form action="." method="post" class="genForm" enctype="multipart/form-data">
{{ form }}
{% csrf_token %}
<button type="submit" name="action" value="addnewsletter">test</button>
</form>

</body>
</html>

#1


2  

Figured it out. It is because of the way I was calling the form in the template. If you change your enctype to multipart you no longer get the error. This in no way is a fix, and you should look at doing this in your form class not a view. But I wanted to figure out why it worked one way and not another.

算出来。这是因为我在模板中调用表单的方式。如果您将enctype更改为multipart,您将不再获得错误。这绝不是一种修复,您应该在表单类而不是视图中进行此操作。但我想弄明白为什么它是用一种方式而不是另一种方式工作的。

<form action="." method="post" class="genForm" enctype="multipart/form-data">

vs

vs

<form action="." method="post" class="genForm">

This seems like it could be a bug in Django (why not enforce in both cases?)

这似乎是Django中的一个bug(为什么不在这两种情况下执行呢?)

Since there seems to be some confusion with this answer I here is a simpler example that shows the same out come:

由于这个答案似乎有些混乱,我这里有一个简单的例子来说明同样的结果:

View :

观点:

def testit(request):
    if request.method == "POST":
        form = testForm(request.POST, request.FILES)
        clean = 'Going to stuff post data with this string'
        if form.is_valid():
            print 'valid'
            request.POST['testOne'] = clean
        else:
            print 'not valid'
            request.POST['testOne'] = clean
    else:
        form = testForm()
    return render_to_response('brag_board/test.html', {'form':form}, context_instance=RequestContext(request))

Form:

形式:

class testForm(forms.Form):
    testOne = forms.CharField(required=True)
    testTwo = forms.CharField(required=True)

Template that gives a error:

出现错误的模板:

<!DOCTYPE html>
<html>
<head>
    <title>test</title>
</head>
<body>

<form action="." method="post" class="genForm">
{{ form }}
{% csrf_token %}
<button type="submit" name="action" value="addnewsletter">test</button>
</form>

</body>
</html>

Template that does not give an error:

没有错误的模板:

<!DOCTYPE html>
<html>
<head>
    <title>test</title>
</head>
<body>

<form action="." method="post" class="genForm" enctype="multipart/form-data">
{{ form }}
{% csrf_token %}
<button type="submit" name="action" value="addnewsletter">test</button>
</form>

</body>
</html>