【问题标题】:'NoneType' object is not subscriptable [duplicate]“NoneType”对象不可下标[重复]
【发布时间】:2017-03-11 21:45:20
【问题描述】:

我正在创建一个 ios 应用程序,它使用用烧瓶 + python 编写的服务器,当我连接到服务器以注册用户时,我的 server.py 文件中不断出现“NoneType”对象不可下标错误.基本上我的问题是是什么导致了这个错误,我该如何解决这个问题。另外,如果有人能指出我正确的方向以不同或更简单的方法来做到这一点,我将不胜感激!

这里是 server.py 文件:

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)

这是我在 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 = ""



}

追溯:

  [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

这里还有 generateBasicAuthHeader 函数:

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
}

【问题讨论】:

  • 显示完整的回溯。错误发生在哪里?无论如何,这意味着你做了类似x[y]xNone 的事情。
  • 所以我猜在我的情况下 request.json['username'] 不起作用,因为 request.json 没有任何价值?
  • 打印request.json,你会看到它是None
  • 所以我的 request.son None 因为我来自 iOS 应用程序的请求没有发送任何数据?我要做的是向我的服务器发送一个发布请求以创建一个用户。
  • 我不确定您为什么需要显示 iOS 代码。错误来自服务器

标签: python rest flask flask-restful


【解决方案1】:

您需要将content-type 显式设置为application/json 以使request.json 在flask 中正常工作。如果未设置标头,request.json 将返回 None。

但建议从 post 请求中获取烧瓶中的 json 数据是使用request.get_json()

我还敦促您在使用 ios 应用程序之前使用漂亮的 requests 模块测试您的 api。

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

它已经设置了发出json 请求所需的适当标头

如果它适用于requests 模块,那么您可以确定它适用于您的ios 应用程序。你只需要确保你设置了正确的content-type

你可以强行告诉flask忽略content-type标头

request.get_json(force=True)

【讨论】:

    猜你喜欢
    • 2016-03-30
    • 2015-02-27
    • 2020-02-22
    • 2021-09-17
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多