Furbeenator
Furbeenator

Reputation: 8285

Django 1.4 form posting forcing method to GET

When I submit a form that has method="POST" the view that handles it is getting method GET, and I can't seem to get it to be a POST, which is necessary for file uploads. Short of just canning my existing (was working a week ago, before upgrade to 1.4) and trying to use the form upload the sample from https://docs.djangoproject.com/en/dev/topics/http/file-uploads/, can you see what is going wrong here? I tried a fresh session using Chrome Incognito with the same results. When I don't include method="POST" it submits with method GET and the fields are included in the request.GET dictionary in the email. However, when I change to POST/post, it remains method GET and the fields are not in the request.POST or the request.GET dictionaries. Is there a bug in Django 1.4 that is causing this behavior? Is there something I'm missing? I tried to make a simple example to rule out all extraneous potential variables.

Simple test scenario:

urls.py:

url(r'^upload_test/+$', 'views.presentation.UploadTest'),
url(r'^uploaded_test/+$', 'views.presentation.UploadedTest'),

views/presentation.py:

def Notify(subject, body):
    """
        Send an email to <to_email>, from <from_email> with the
        subject and body supplied.
    """
    send_mail(subject, body, '<from_email>', ['<to_email>'], fail_silently=False)

def UploadTest(request):
    Notify("UploadTest", "METHOD: " + str(request.method) + """

    """ + str(request))
    return render_to_response('upload.htm', context_instance=RequestContext(request))

def UploadedTest(request):
    Notify("UploadedTest", "METHOD: " + str(request.method) + """

    """ + str(request) + """

    FILES:
    """ + str(request.FILES))
    return render_to_response('upload.htm', context_instance=RequestContext(request))

upload.htm (note method is POST, I tried lowercase just in case as well):

<form
    id="upload_file_form"
    action="/uploaded_test"
    method="POST"
    enctype="multipart/form-data"
    target="_blank"
>
    {% csrf_token %}
    <input type="text" name="extra_field" value="extra post field" />
    <input type="file" name="upload_file" id="upload_file" />
    <input type="submit" name="upload" value="Submit" />
</form>

Results of simple test scenario

The emails I get (note the first is the form pre-submit, the second is the posted form page):

FIRST EMAIL (subject "UploadTest"):

METHOD: GET

<WSGIRequest
    path:/upload_test/,
    GET:<QueryDict: {}>,
    POST:<QueryDict: {}>,
    COOKIES:{
        'csrftoken': '...',
        'sessionid': '...'},
    META:{'CSRF_COOKIE': '...',
    'DOCUMENT_ROOT': '...',
    'GATEWAY_INTERFACE': 'CGI/1.1',
    'HTTPS': '1',
    'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
    'HTTP_ACCEPT_LANGUAGE': 'en-us,en;q=0.5',
    'HTTP_CONNECTION': 'keep-alive',
    'HTTP_COOKIE': '... csrftoken=...; CFID=16005; CFTOKEN=...; sessionid=...',
    'HTTP_HOST': '...',
    'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:11.0) Gecko/20100101 Firefox/11.0',
    'PATH_INFO': u'/upload_test/',
    'PATH_TRANSLATED': '...site.wsgi/upload_test/',
    'QUERY_STRING': '',
    'REMOTE_ADDR': '10.1.0.100',
    'REMOTE_PORT': '56037',
    'REQUEST_METHOD': 'GET',
    'REQUEST_URI': '/upload_test/',
    'SCRIPT_FILENAME': '...site.wsgi',
    'SCRIPT_NAME': u'',
    'SERVER_ADDR': '10.1.10.12',
    'SERVER_ADMIN': '...',
    'SERVER_NAME': '...',
    'SERVER_PORT': '443',
    'SERVER_PROTOCOL': 'HTTP/1.1',
    'SERVER_SIGNATURE': '',
    'SERVER_SOFTWARE': 'Apache',
    'SSL_TLS_SNI': '...',
    'mod_wsgi.application_group': '...|',
    'mod_wsgi.callable_object': 'application',
    'mod_wsgi.handler_script': '',
    'mod_wsgi.input_chunked': '0',
    'mod_wsgi.listener_host': '',
    'mod_wsgi.listener_port': '443',
    'mod_wsgi.process_group': '',
    'mod_wsgi.request_handler': 'wsgi-script',
    'mod_wsgi.script_reloading': '1',
    'mod_wsgi.version': (3, 3),
    'wsgi.errors': <mod_wsgi.Log object at 0x1962048>,
    'wsgi.file_wrapper': <built-in method file_wrapper of mod_wsgi.Adapter object at 0xb73d2770>,
    'wsgi.input': <mod_wsgi.Input object at 0x1962020>,
    'wsgi.multiprocess': True,
    'wsgi.multithread': True,
    'wsgi.run_once': False,
    'wsgi.url_scheme': 'https',
    'wsgi.version': (1, 1)}>

SECOND EMAIL (subject "UploadedTest", method is STILL "GET", notice HTTP_REFERER is correct, and request.FILES exists, but is empty.):

METHOD: GET

<WSGIRequest
    path:/uploaded_test/,
    GET:<QueryDict: {}>,
    POST:<QueryDict: {}>,
    COOKIES:{
        'csrftoken': '...',
        'sessionid': '...'
    },
    META:{'CSRF_COOKIE': '...',
    'DOCUMENT_ROOT': '...',
    'GATEWAY_INTERFACE': 'CGI/1.1',
    'HTTPS': '1',
    'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
    'HTTP_ACCEPT_LANGUAGE': 'en-us,en;q=0.5',
    'HTTP_CONNECTION': 'keep-alive',
    'HTTP_COOKIE': 'csrftoken=...; sessionid=...',
    'HTTP_HOST': '...',
    'HTTP_REFERER': '.../upload_test/',
    'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:11.0) Gecko/20100101 Firefox/11.0',
    'PATH_INFO': u'/uploaded_test/',
    'PATH_TRANSLATED': '...site.wsgi/uploaded_test/',
    'QUERY_STRING': '',
    'REMOTE_ADDR': '10.1.0.100',
    'REMOTE_PORT': '56040',
    'REQUEST_METHOD': 'GET',
    'REQUEST_URI': '/uploaded_test/',
    'SCRIPT_FILENAME': '...site.wsgi',
    'SCRIPT_NAME': u'',
    'SERVER_ADDR': '10.1.10.12',
    'SERVER_ADMIN': '...',
    'SERVER_NAME': '...',
    'SERVER_PORT': '443',
    'SERVER_PROTOCOL': 'HTTP/1.1',
    'SERVER_SIGNATURE': '',
    'SERVER_SOFTWARE': 'Apache',
    'SSL_TLS_SNI': '...',
    'mod_wsgi.application_group': '...|',
    'mod_wsgi.callable_object': 'application',
    'mod_wsgi.handler_script': '',
    'mod_wsgi.input_chunked': '0',
    'mod_wsgi.listener_host': '',
    'mod_wsgi.listener_port': '443',
    'mod_wsgi.process_group': '',
    'mod_wsgi.request_handler': 'wsgi-script',
    'mod_wsgi.script_reloading': '1',
    'mod_wsgi.version': (3, 3),
    'wsgi.errors': <mod_wsgi.Log object at 0x1956b88>,
    'wsgi.file_wrapper': <built-in method file_wrapper of mod_wsgi.Adapter object at 0x21cf0f8>,
    'wsgi.input': <mod_wsgi.Input object at 0x1961048>,
    'wsgi.multiprocess': True,
    'wsgi.multithread': True,
    'wsgi.run_once': False,
    'wsgi.url_scheme': 'https',
    'wsgi.version': (1, 1)}>

    FILES:
    <MultiValueDict: {}>

Doubtful, but perhaps it is something wrong in my wsgi file, or in my Apache site directive. Here are those, just in case:

...wsgi:

import os
import sys

path = '/var'
if path not in sys.path:
   sys.path.append(path)

path = '/var/www'
if path not in sys.path:
   sys.path.append(path)

path = '/var/www/site'
if path not in sys.path:
   sys.path.append(path)

os.environ['DJANGO_SETTINGS_MODULE'] = 'site.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Apache sites-enabled directive:

<VirtualHost 10.1.10.12:80>
    ServerName ...
    RewriteEngine on
    RewriteCond %{HTTPS} !=on
    RewriteRule ^/(.*) https://%{SERVER_NAME}/$1 [R,L]
</VirtualHost>


<Directory /var/www/site>
    RewriteEngine on
    RewriteCond 1 =1
    RewriteRule ^/(.*) https://%{SERVER_NAME}
</Directory>


<VirtualHost 10.1.10.12:443>
    ServerName ...
    DocumentRoot /var/www/site
    ServerAlias ...
    ErrorLog /var/log/apache2/site-error.log
    LogLevel warn
    CustomLog /var/log/apache2/site-access.log combined
    WSGIScriptAlias / /var/www/site/site.wsgi
    SSLEngine on
    SSLCertificateFile ...
    SSLCertificateKeyFile ...

    # Media serving, must specify which files to serve and not
    # hand their urls to the django framework.
    Alias /robots.txt .../robots.txt
    Alias /favicon.ico .../favicon.ico

    Alias /templates/ .../django_templates/
    Alias /static/ .../django_static/
    Alias /images/ .../django_static/images/

    <Directory /usr/local/lib/python2.6/dist-packages/django/contrib/admin/media/>
            Order deny,allow
            Allow from all
    </Directory>

    <Directory .../django_static/>
            Order deny,allow
            Allow from all
    </Directory>

    <Directory /usr/local/lib/python2.6/dist-packages/django/contrib/admin/media/js>
            Order allow,deny
            Allow from all
    </Directory>

    <Directory .../uploads/>
            Order allow,deny
            Allow from all
    </Directory>

    XSendFile on

Upvotes: 1

Views: 1469

Answers (2)

Furbeenator
Furbeenator

Reputation: 8285

Perhaps I need to read more about the urls.py or regular expression. I accidentally changed the form to post to action="uploaded_test" without the opening slash, and received a 404 error report which has the request.method as "POST," (what the ?!@#$*&)...??? This meant that it had to be something with my posting url! I had it as:

'^uploaded_test/+$'

I changed it to:

'^uploaded_test$'

and verified the form was posting to action="/uploaded_test" and it worked! I changed urls.py to:

'^uploaded_test/$'

and changed the form to post to action="/uploaded_test/" and it also worked! I had the /+ in most of my urls entries so that I could accept either /loc or /loc/ for many entries. I think I will change them back, now. I don't know if this is a bug or something I don't understand about the regular expression /+ syntax.

Upvotes: 2

Frantz Romain
Frantz Romain

Reputation: 846

Have you tried an if-else statement in your presentation layer?. for example if request.method == 'POST': and then the rest of your code.

Upvotes: 1

Related Questions