'NoneType' object is not subscriptable

26,927

You need to explicitly set the content-type to application/json for request.json to work properly in flask. If the header isn't set, request.json would return None.

But the recommended to get json data in flask from a post request is to use request.get_json()

I'll also urge you to test your api with the nifty requests module before using your ios application.

>>> import requests
>>> requests.post(url, json={'name': 'hello world'})

It already sets the appropriate headers required to make a json request

If it works with the requests module, then you can be sure that it's going to work with your ios application. you just need to make sure you're setting the correct content-type.

You can forcefully tell flask to ignore the content-type header with

request.get_json(force=True)

Share:
26,927
Lucas Padden
Author by

Lucas Padden

Updated on July 05, 2022

Comments

  • Lucas Padden
    Lucas Padden almost 2 years

    I am creating an ios app that uses a server written in flask + python, and when I make a connection to the server to register a user I keep getting a 'NoneType' object is not subscriptable error in my server.py file. Basically my question is what is causing this error and how am I able to fix this. Also if anyone can point me in the right direction of different or easier ways to do this I would appreciate it thanks!

    Here is the server.py file:

    import bcrypt
    from flask import Flask, request, make_response,jsonify
    from flask_restful import Resource, Api
    from pymongo import MongoClient
    from json import JSONEncoder
    from bson.objectid import ObjectId
    from functools import wraps
    
    
    app = Flask(__name__)
    
    mongo = MongoClient('localhost', 27017)
    
    app.db = mongo.eventure_db
    
    app.bcrypt_rounds = 12
    
    api = Api(app)
    
    # Authentication code.
    def check_auth(username, password):
        # check_auth should access the database and check if the username +  password are correct.
        # create a collection to hold the users.
    
       user_collection = app.db.users
       user = user_collection.find_one({'username': username})
    
       if user is None:
            return False
        else:
            # check if hash generated matches stored hash
            encodedPassword = password.encode('utf-8')
            if bcrypt.hashpw(encodedPassword, user['password']) == user['password']:
                return True
            else:
                return False
    
    
    
    # User resource
    
    class User(Resource):
    
       def post(self):
            if (request.json['username'] == None
                    or request.json['password'] == None):
                    return ({'error':  'Request requires username and password'},
                        400,
                        None)
    
            user_collection = app.db.users
            user = user_collection.find_one({'username':       request.json['username']})
    
            if user is not None:
                return ({'error': 'Username already in use'}, 400, None)
            else:
                encodedPassword = request.json['password'].encode('utf-8')
                hashed = bcrypt.hashpw(
                    encodedPassword, bcrypt.gensalt(app.bcrypt_rounds))
                request.json['password'] = hashed
                user_collection.insert_one(request.json)
    
        @requires_auth
        def get(self):
            return (None, 200, None)
    
    
    api.add_resource(User, '/eventure/api/v1.1/user/')
    
    # Must define a custom JSON Serializer for flask_restful
    # this is because ObjectId is not a string, and therefore,
    # Flask's default serializer cannot serialize it.
    
    @api.representation('application/json')
    def output_json(data, code, headers=None):
    
        resp = make_response(JSONEncoder().encode(data), code)
        resp.headers.extend(headers or {})
            return resp
    
    
    
    if __name__ == '__main__':
        app.config['TRAP_BAD_REQUEST_ERRORS'] = True
        app.run(host='localhost', port=8789, debug=True)
    

    And this is my register function in swift:

    @IBAction func register(_ sender: AnyObject) {
    
        let url = URL(string: "http://localhost:8789/eventure/api/v1.1/user/")
    
        var request = URLRequest(url: url!)
    
        request.httpMethod = "POST"
    
        request.setValue(generateBasicAuthHeader(username: username.text!, password: password.text!), forHTTPHeaderField: "Authorization")
    
    
        let session = URLSession.shared
    
        let task = session.dataTask(with: request) { data, response, error in
            if let response = response, let data = data {
                print(String(data: data, encoding: String.Encoding.utf8))
            }
        }
    
        task.resume()
    
    
    
    
        self.username.text = ""
        self.password.text = ""
    
    
    
    }
    

    traceback:

      [28/Oct/2016 19:22:33] "POST /eventure/api/v1.1/user/ HTTP/1.1" 500 -
      Traceback (most recent call last):
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1836, in __call__
        return self.wsgi_app(environ, start_response)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1820, in wsgi_app
        response = self.make_response(self.handle_exception(e))
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask_restful/__init__.py", line 270, in error_router
        return original_handler(e)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1403, in handle_exception
        reraise(exc_type, exc_value, tb)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/_compat.py", line 32, in reraise
        raise value.with_traceback(tb)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1817, in wsgi_app
        response = self.full_dispatch_request()
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1477, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask_restful/__init__.py", line 270, in error_router
        return original_handler(e)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1381, in handle_user_exception
        reraise(exc_type, exc_value, tb)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/_compat.py", line 32, in reraise
        raise value.with_traceback(tb)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1475, in full_dispatch_request
        rv = self.dispatch_request()
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1461, in dispatch_request
        return self.view_functions[rule.endpoint](**req.view_args)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask_restful/__init__.py", line 471, in wrapper
        resp = resource(*args, **kwargs)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/views.py", line 84, in view
        return self.dispatch_request(*args, **kwargs)
      File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask_restful/__init__.py", line 581, in dispatch_request
        resp = meth(*args, **kwargs)
      File "/Users/Dynee/eventure-backend-api/server.py", line 128, in post
        if (request.json['username'] == None
    TypeError: 'NoneType' object is not subscriptable
    

    Also here is the generateBasicAuthHeader function:

    func generateBasicAuthHeader(username: String, password: String) -> String {
    
        let loginString = String(format: "%@:%@", username, password)
        let loginData = loginString.data(using: String.Encoding.utf8)!
        let base64LoginString = loginData.base64EncodedString()
        let basicAuthHeader = "Basic \(base64LoginString)"
        return basicAuthHeader
    }