Reputation: 668
I am trying to create FileField in my forms and without saving file locally, add the file(as an attachment) to email and send it. Email part of code works fine, but when i add FileField it shows me error "'str' object has no attribute 'get'" and i am struggling to figure out what is the problem.
view:
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)
form:
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:"
here is HTML code snippet, where i call for the form:
<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>
Environment:
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']
And that's the error i'm getting:
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'
After removing try-except case from views, i m getting following traceback: Traceback:
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:
Any help would be very much appreciated. Thanks!
Upvotes: 1
Views: 1732
Reputation: 1949
It looks like the clickjacking middleware is blowing up because the response its reading is a string when it should be something else.
Looking at your code this line might be the culprit return "Attachment error"
try changing it to
return HttpResponse('Attachment error')
you can import HttpResponse like this from django.http import HttpResponse
Upvotes: 1
Reputation: 53386
You should not use request.POST
and request.FILES
to populate the model/DB. You should use data from form.
So for the file field you should do
uploaded_file = form.cleaned_data['stl_file']
Also, don't do, use data from form.cleaned_data
contact_name = request.POST.get('contact_name', '')
Rather use
contact_name = form.cleaned_data.get('contact_name', '')
Upvotes: 0