mr. Di
mr. Di

Reputation: 35

How to respond to ajax in a simple wsgi app?

for training purposes I try to make a simple wsgi application, need help with a few questions. Thanks in advance to all who answer!
I have the following code:

from wsgiref.simple_server import make_server
import re


def collectTemplate(body):
    header_html = open('templates/header.html', encoding='utf-8').read()
    footer_html = open('templates/footer.html', encoding='utf-8').read()
    html = header_html + body + footer_html
    return html.encode('utf-8')

def indexPage(environ, start_response):
    path = environ.get('PATH_INFO')
    print(path)
    status = '200 OK'
    headers = [("Content-type", "text/html; charset=utf-8")]
    start_response(status, headers)
    body = """
        <h1>Hello index</h1>
        <div class='send'>Send ajax</div>
        <script>
            $('.sjd').on('click', function(){
                $.ajax({
                    type: 'POST',
                    dataType: 'json',
                    data: {'data': 'hello'},
                    url: 'ajax.py',
                    success: function (msg) {
                        console.log(msg)
                    },
                    error : function (msg){
                        console.log(msg)
                    }
                });
            });
        </script
        """
    html = collectTemplate(body)
    return [html.encode('utf-8')]

def anotherPage(environ, start_response):
    status = '200 OK'
    headers = [("Content-type", "text/html; charset=utf-8")]
    start_response(status, headers)
    body = "<h1>Hello another page</h1>"
    html = collectTemplate(body)
    return [html.encode('utf-8')]

def page404(environ, start_response):
    start_response('404 NOT FOUND', [('Content-Type', 'text/html')])
    return ['Not Found']

urls = [
    (r'^$', indexPage),
    (r'another/?$', anotherPage),
]

def application(environ, start_response):
    path = environ.get('PATH_INFO', '').lstrip('/')
    for regex, callback in urls:
        match = re.search(regex, path)
        if match is not None:
            environ['url_args'] = match.groups()
            return callback(environ, start_response)
    return page404(environ, start_response)

if __name__ == '__main__':
    srv = make_server('', 8000, application)
    srv.serve_forever()

Question 1) The most important how to implement ajax and answer it? I would be very grateful for examples. I tried in ajax.py the following code, but it gave no result

import cgi
storage = cgi.FieldStorage()
data = storage.getvalue('data')
print('Status: 200 OK')
print('Content-Type: text/plain')
print('')
if data is not None:
    print(data)

Question 2) When you start, there are two page (127.0.0.1:8000) and (127.0.0.1:8000/another/) when you switch everything works but the console gets the error. why this is happening?

File "C:\Python\Python37-32\lib\wsgiref\simple_server.py", line 35, in close
self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'

Upvotes: 1

Views: 373

Answers (2)

mr. Di
mr. Di

Reputation: 35

Thank you for sending us on the right path, the solution looks like this

 def ajax(environ, start_response): 
        start_response('200 OK', [('Content-Type', 'text/json')])
        json_string = json.dumps({'status':'ok'})
        return [json_string.encode()]

Upvotes: 0

Ruben Helsloot
Ruben Helsloot

Reputation: 13129

AJAX requests are simply like any other requests, except you often return data, a partial template, or a file. To create an endpoint for an AJAX request, simply do the same thing as you've done before. Create a function and add that function as an endpoint. Remove the .py extension from the url you pass in the tag.

import cgi

def handle_ajax(environ, start_response):
  storage = cgi.FieldStorage()
  data = storage.getvalue('data')
  print('Status: 200 OK')
  print('Content-Type: text/plain')
  print('')
  if data is not None:
    print(data)


urls [..., (r'ajax', handle_ajax)]

As for your second question, this is really weird. It looks a lot like self.status is None, even though it should be set to the status you pass in start_response. Can you extend your question with more of the stacktrace? Also, maybe try passing named arguments start_response(status=status, headers=headers)

Upvotes: 1

Related Questions