【问题标题】:FileField not processed on form POSTFileField 未在表单 POST 上处理
【发布时间】:2014-08-17 19:26:28
【问题描述】:

当尝试使用 FileField 上传文件时,表单不会将文件数据发布到服务器。 如果您使用文本字段,它会完美运行,但由于某种原因它无法识别文件,因为它不能 显示在 request.FILES 或 request.POSTS 上。

MEDIA_ROOT 和 MEDIA_URL 配置:

MEDIA_ROOT = '/home/grove/pootleImages/'
MEDIA_URL = '/pootleImages/'

get_unit_context 在 decorators.py 中的装饰器:

def get_unit_context(permission_codes):

def wrap_f(f):

    @wraps(f)
    def decorated_f(request, uid, *args, **kwargs):
        unit = get_object_or_404(
                Unit.objects.select_related("store__translation_project",
                                            "store__parent"),
                id=uid,
        )
        _common_context(request, unit.store.translation_project,
                        permission_codes)
        request.unit = unit
        request.store = unit.store
        request.directory = unit.store.parent

        return f(request, unit, *args, **kwargs)

    return decorated_f

return wrap_f

我的 forms.py 方法:

def unit_image_form_factory(language):

    image_attrs = {
        'lang': language.code,
        'dir': language.direction,
        'class': 'images expanding focusthis',
        'rows': 2,
        'tabindex': 15,
    }


    class UnitImageForm(forms.ModelForm):

        class Meta:
            fields = ('image',)
            model = Unit

        # It works if using a CharField!
        #image = forms.CharField(required=True,
          #                                   label=_("Image"),
           #                                  widget=forms.Textarea(
            #                                 attrs=image_attrs))
        image= forms.FileField(required=True, label=_('Image'),
                                             widget=forms.FileInput(
                                             attrs=image_attrs))
        def __init__(self, *args, **kwargs):
            self.request = kwargs.pop('request', None)
            super(UnitImageForm, self).__init__(*args, **kwargs)


        def save(self):
            super(UnitImageForm, self).save()


    return UnitImageForm

我的models.py sn-p:

class Unit(models.Model, base.TranslationUnit):
    # ...
    # ...
    # It works if using a TextField!
    #image = models.TextField(null=True, blank=True)
    image = models.FileField(upload_to=".", blank=True, null=True)
    # ...
    # ...

我的 urls.py sn-p:

url(r'^xhr/units/(?P<uid>[0-9]+)/image/?$',
    'image',
    name='pootle-xhr-units-image'),

我的views.py方法:

@require_POST
@ajax_required
@get_unit_context('translate')
def image(request, unit):
    """Stores a new image for the given ``unit``.

    :return: If the form validates, the cleaned image is returned.
             An error message is returned otherwise.
    """
    # Update current unit instance's attributes
    unit.uploaded_by = request.profile
    unit.uploaded_on = timezone.now()

    language = request.translation_project.language
    form = unit_image_form_factory(language)(request.POST, request.FILES, instance=unit,
                                               request=request)

    if form.is_valid():
        form.save()
        context = {
            'unit': unit,
            'language': language,
        }
        t = loader.get_template('unit/image.html')
        c = RequestContext(request, context)

        json = {'image': t.render(c)}
        rcode = 200
    else:
        json = {'msg': _("Image submission failed.")}
        rcode = 400

    response = simplejson.dumps(json)

    return HttpResponse(response, status=rcode, mimetype="application/json")

我的图片上传 HTML 模板:

<div id="upload-image">
    <form enctype="multipart/form-data" method="post" action="{% url 'pootle-xhr-units-image' unit.id %}" id="image-form">
    {% csrf_token %}
    <input type="file" name="image" id="id_image" />
    <p><input type="submit" value="{% trans 'Upload' %}" /></p>
    </form>
</div>

当表单实例化时,request.POST 不返回用户浏览过的文件,request.FILES 也不返回。 form.errors 只返回"This field is required" 表单对象返回以下内容:

<tr><th><label for="id_image">Image:</label></th><td><ul class="errorlist"><li>This field is required.</li>
</ul><input lang="pl" rows="2" name="image" id="id_image" type="file" class="images expanding focusthis" dir="ltr" tabindex="15" /></td></tr>

而当用户点击提交按钮时,会出现如下POST错误:

"POST /xhr/units/74923/image HTTP/1.1" 400 35

我可以通过在 image 属性中包含 required=False 来绕过它,但无论如何都不会发布该文件。

更多输出调试信息:

需要fileField时POST=True:

状态代码:400 错误请求 表格数据: csrfmiddlewaretoken:yoTqPAAjy74GH

form.errors:

“味精”:“

  • 图片
  • 此字段为必填项。
  • "}

    如果将 required=True 更改为 required=False:

    状态码:200 OK 表格数据: csrfmiddlewaretoken:yoTqPAAjy74GH

    但是图像字段仍然没有显示在表单数据中。

    谢谢,

    亚历克斯


    我添加了一个包含与此问题相关的所有文件的 gist hub,以简化可视化:

    https://gist.github.com/alex-silva/40313734b9f1cd37f204

    【问题讨论】:

      标签: python django file upload


      【解决方案1】:

      您似乎忘记在表单中添加 {% csrf_token %}。在标签之间添加。

      或者...

      您可以将 csrf_exempt 装饰器添加到您的处理视图中:

      from django.views.decorators.csrf import csrf_exempt
      from django.http import HttpResponse
      
      @csrf_exempt
      def my_view(request):
          return HttpResponse('Hello world')
      

      更多信息:https://docs.djangoproject.com/en/dev/ref/contrib/csrf/

      【讨论】:

      • 感谢您的回复。抱歉,我放入 cmets 的 HTML 已过时,表单中有 {% csrf_token %}。我尝试了 csrf_exempt,但该文件仍未显示在 request.FILES 或 request.POST 中。奇怪的是,当我使用 csrf_exempt (并删除 {% csrf_token %} 时,csrfmiddlewaretoken 仍然出现在 request.POST 中。知道发生了什么吗?该表单非常适用于文本字段。我用更多信息更新了描述.
      【解决方案2】:

      终于设法让它以某种方式工作。在主页中使用该表单时,该表单根本不起作用,因此我创建了一个指向仅包含上传图像表单的空白页面的链接。当与主页分开时,上传工作正常。然后我只是在上传后重定向到主页。为什么表单在主页中不起作用,这是个谜。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-28
        • 2011-04-22
        • 1970-01-01
        • 2014-03-15
        • 2016-06-23
        • 1970-01-01
        • 1970-01-01
        • 2021-01-06
        相关资源
        最近更新 更多