FileField не работает в Django

Я пытаюсь создать FileField в моих формах и, не сохраняя файл локально, добавить файл (как вложение) в электронное письмо и отправить его. Электронная часть кода работает нормально, но когда я добавляю FileField, он показывает мне ошибку "У объекта str нет атрибута 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, где я вызываю форму:

<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'

После удаления пробного случая из представлений я получаю следующую трассировку: Трассировка:

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: 

Любая помощь будет очень высоко ценится. Спасибо!

2 ответа

Решение

Похоже, что промежуточное ПО для clickjacking взорвалось, потому что ответ, который он читает, является строкой, когда должно быть что-то еще.

Глядя на ваш код, эта строка может быть виновником return "Attachment error"

попробуйте изменить его на

return HttpResponse('Attachment error')

Вы можете импортировать HttpResponse, как это from django.http import HttpResponse

Вы не должны использовать request.POST а также request.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', '')
Другие вопросы по тегам