【问题标题】:FileField not working in DjangoFileField 在 Django 中不起作用
【发布时间】:2017-04-18 05:37:14
【问题描述】:

我正在尝试在我的表单中创建 FileField,并且没有在本地保存文件,而是将文件(作为附件)添加到电子邮件并发送。代码的电子邮件部分工作正常,但是当我添加 FileField 时,它显示错误“'str' object has no attribute 'get'”,我正在努力找出问题所在。

查看:

def print(request):
    if request.method == 'POST':
        form = PrintForm(data=request.POST, request = request)
        #print(request.FILES)

        if form.is_valid():
            contact_name = request.POST.get('contact_name', '')
            contact_email = request.POST.get('contact_email', '')
            form_content = request.POST.get('content', '')
            supervisor = form.cleaned_data['supervisor']
            template = get_template('threeD/email/contact_template_for_printing.txt')
            context = Context({
                'contact_name': contact_name,
                'supervisor': supervisor,
                'contact_email': contact_email,
                'form_content': form_content,
            })
            content = template.render(context)
            subject = "New message"

            try:
                email = EmailMessage(
                    subject,
                    content,
                    contact_email,
                    [supervisor],
                    headers={'Reply-To': contact_email}
                )
                if request.FILES:
                    #uploaded_file = request.POST.get('file')

                    uploaded_file = request.FILES['stl_file']  # file is the name value which you have provided in form for file field
                    email.attach('uploaded_file.name, uploaded_file.read(), uploaded_file.content_type')
                email.send()
            except:
                return "Attachment error"

            messages.success(request, "Thank you for your message.")
            return redirect('/index/print/')

    else:
        form = PrintForm(request=request)

    context_dict = {}
    context_dict['printers'] = Printer.objects.all()
    context_dict['form'] = form
    return render(request, 'threeD/print.html', context_dict)

表格:

class PrintForm(forms.Form):
    contact_name = forms.CharField(required=True)
    contact_email = forms.EmailField(required=True)
    supervisor = forms.ChoiceField(
        choices=[(str(sup.email), str(sup.name)) for sup in Supervisors.objects.all()]
    )
    stl_file = forms.FileField(required=False)
    stl_file.help_text = "Upload your file as .STL format. If you have more than one file, " \
                     "make a .zip and upload them all at once"
    content = forms.CharField(
        required=True,
        widget=forms.Textarea
    )

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super(PrintForm, self).__init__(*args, **kwargs)
        self.fields['contact_name'].label = "Your name:"
        self.fields['stl_file'].label = "Choose your design file:"

这里是 HTML 代码 sn-p,我在这里调用表单:

<div class="panel-body">
  <form role="form" action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {% load bootstrap %}
    {{ form|bootstrap }}          
    <div class="text-center">
      <button type="submit" class="btn btn-primary">
        <span class="glyphicon glyphicon-send"></span>
        Send a message
      </button>
    </div>
  </form>
</div>

环境:

Request Method: POST
Request URL: http://localhost:8000/index/print/

Django Version: 1.9
Python Version: 3.4.3

Installed Applications:
['admin_tools',
 'admin_tools.theming',
 'admin_tools.menu',
 'admin_tools.dashboard',
 'threeD.apps.ThreedConfig',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'bootstrapform',
 'django.contrib.sites',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'allauth.socialaccount.providers.facebook']

Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']

这就是我得到的错误:

Traceback:

File "C:\Python34\lib\site-packages\django-1.9-py3.4.egg\django\core\handlers\base.py" in get_response
  235.                 response = middleware_method(request, response)

File "C:\Python34\lib\site-packages\django-1.9-py3.4.egg\django\middleware\clickjacking.py" in process_response
  31.         if response.get('X-Frame-Options') is not None:

Exception Type: AttributeError at /index/print/
Exception Value: 'str' object has no attribute 'get'

从视图中删除 try-except 案例后,我得到以下回溯: 追溯:

File "C:\Python34\lib\site-packages\django-1.9-py3.4.egg\django\core\handlers\base.py" in get_response
  149.                     response = self.process_exception_by_middleware(e, request)

File "C:\Python34\lib\site-packages\django-1.9-py3.4.egg\django\core\handlers\base.py" in get_response
  147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "E:\Python\Facility\threeD\views.py" in print
  145.                 email.attach('uploaded_file.name, uploaded_file.read(), uploaded_file.content_type')

File "C:\Python34\lib\site-packages\django-1.9-py3.4.egg\django\core\mail\message.py" in attach
  307.             assert content is not None

Exception Type: AssertionError at /index/print/
Exception Value: 

任何帮助将不胜感激。谢谢!

【问题讨论】:

    标签: python django forms filefield


    【解决方案1】:

    看起来点击劫持中间件正在爆炸,因为它读取的响应是一个字符串,而它应该是别的东西。

    看看你的代码这行可能是罪魁祸首return "Attachment error"

    试试改成

    return HttpResponse('Attachment error')

    你可以像from django.http import HttpResponse这样导入HttpResponse

    【讨论】:

    • 感谢您的留言,戴维德琼斯。我尝试更改代码以返回 HttpResponse('Attachment error'),当我提交表单时,它显然被我的 try-except 捕获并返回空白屏幕并显示文本“附件错误”
    • 太好了,这样就解决了您现在遇到的直接错误,您可以继续解决为什么它会进入 try catch。您应该在 catch 中记录/输出错误或完全删除 try catch,以便看到错误。
    • 嗯,这很好。现在我收到错误:/index/print/ 处的 AssertionError(这是我的模板,我正在调用)没有提供异常消息
    • 我已经用我当前错误的回溯更新了这个问题。在我看来,我附加文件(从缓冲区)的方式不正常
    • 从附加方法中删除''括号后,它成功传递了该行,但在 email.send() 行上显示错误为:“需要超过 1 个值才能解包”。该死,我对这一切感到很困惑
    【解决方案2】:

    您不应使用request.POSTrequest.FILES 来填充模型/数据库。您应该使用表单中的数据。

    所以对于文件字段你应该这样做

    uploaded_file = form.cleaned_data['stl_file'] 
    

    另外,不要这样做,使用来自form.cleaned_data的数据

    contact_name = request.POST.get('contact_name', '')
    

    相当使用

    contact_name = form.cleaned_data.get('contact_name', '')
    

    【讨论】:

    • 感谢您的评论,罗汉。我试过使用uploaded_file = form.cleaned_data['stl_file'],但没有运气。它仍然爆炸并显示相同的错误:/我也尝试过使用 contact_name = form.cleaned_data.get('contact_name', '') 方法,但它显示错误:'dict' object is not callable跨度>
    猜你喜欢
    • 2012-08-12
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    • 2014-06-25
    • 2016-01-09
    • 2015-09-15
    相关资源
    最近更新 更多