Я пытаюсь получить ноги в разработке API. Я беру большинство своих заметок из этой статьи.
Пока у меня нет проблем с curl requests
на curl requests
для GET
, POST
или DELETE
. PUT
запросы PUT
возвращают ошибку 404
.
Вот код API, с которым я занимаюсь:
class UserAPI(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument('name', type = str, required = True, help = "No name provided", location = 'json')
self.reqparse.add_argument('email', type = str, required = True, help = "No email provided", location = 'json')
self.reqparse.add_argument('password', type = str, required = True, help = "No password provided", location = 'json')
super(UserAPI, self).__init__()
def get(self, id):
if checkUser(id): #Just checks to see if user with that id exists
info = getUserInfo(id) #Gets Users info based on id
return {'id': id, 'name': info[0], 'email':info[1], 'password': info[2], 'role': info[3]}
abort(404)
def put(self, id):
if checkUser(id):
args = self.reqparse.parse_args()
deleteUser(id) #Deletes user with this id
addUser(User(args['name'], args['email'], args['password'], args['role'])) #Adds user to database
abort(404)
def delete(self, id):
deleteUser(id)
return { 'result': True}
class UserListAPI(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument('name', type = str, required = True, help = "No name provided", location = 'json')
self.reqparse.add_argument('email', type = str, required = True, help = "No email provided", location = 'json')
self.reqparse.add_argument('password', type = str, required = True, help = "No password provided", location = 'json')
self.reqparse.add_argument('role', type = bool, default = 0, location = 'json')
super(UserListAPI, self).__init__()
def get(self):
return { 'users': map(lambda u: marshal(u, user_fields), getAllUsers()) }
def post(self):
print self.reqparse.parse_args()
args = self.reqparse.parse_args()
new_user = User(args['name'], args['email'], args['password'], args['role'])
addUser(new_user)
return {'user' : marshal(new_user, user_fields)}, 201
api.add_resource(UserAPI, '/api/user/<int:id>', endpoint = 'user')
api.add_resource(UserListAPI, '/api/users/', endpoint = 'users')
В принципе, один класс обрабатывает просмотр всех пользователей или добавляет пользователя в БД (UserListAPI), а другие ручки получают отдельных пользователей, обновляют пользователя или удаляют пользователя (UserAPI).
Как я уже сказал, все работает PUT
.
Когда я curl -H 'Content-Type: application/json' -X PUT -d '{"name": "test2", "email":"[email protected]", "password":"testpass", "role": 0}' http://127.0.0.1:5000/api/user/2
Я получаю следующую ошибку:
{
"message": "Not Found. You have requested this URI [/api/user/2] but did you mean /api/user/<int:id> or /api/users/ or /api/drinks/<int:id> ?",
"status": 404
}
Это не имеет смысла для меня. Не следует ли <int:id>
принять целое число, указанное в конце URL-адреса?
Спасибо за любые мысли
РЕДАКТИРОВАТЬ
Было указано обновление моего ответа после тупой ошибки с моей стороны. Теперь метод put выглядит следующим образом:
def put(self, id):
if checkUser(id):
args = self.reqparse.parse_args()
deleteUser(id)
user = User(args['name'], args['email'], args['password'], args['role'])
addUser(user)
return {'user' : marshal(user, user_fields)}, 201
else:
abort(404)
Вы не возвращаетесь, когда PUT sucees, поэтому всегда прерывается (404). Как и в других HTTP-глаголах:
def put(self, id):
if checkUser(id):
args = self.reqparse.parse_args()
deleteUser(id) #Deletes user with this id
addUser(User(args['name'], args['email'], args['password'], args['role']))
# Missing return when succees
abort(404) # Always executing
EDIT: Я проверил ваш пример (с некоторым дополнительным кодом, чтобы он работал, например, импорт и удаление определенного кода не реализованы). Это мой код:
from flask import Flask
from flask.ext.restful import Api, Resource
from flask.ext.restful import reqparse
app = Flask(__name__)
api = Api(app)
class UserAPI(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument('name', type = str, required = True, help = "No name provided", location = 'json')
self.reqparse.add_argument('email', type = str, required = True, help = "No email provided", location = 'json')
self.reqparse.add_argument('password', type = str, required = True, help = "No password provided", location = 'json')
super(UserAPI, self).__init__()
def get(self, id):
if True: #Just checks to see if user with that id exists
return {"message": "You have GET me"}
abort(404)
def put(self, id):
if True:
return {"message": "You have PUT me"}
abort(404)
def delete(self, id):
deleteUser(id)
return { 'result': True}
class UserListAPI(Resource):
def __init__(self):
self.reqparse = reqparse.RequestParser()
self.reqparse.add_argument('name', type = str, required = True, help = "No name provided", location = 'json')
self.reqparse.add_argument('email', type = str, required = True, help = "No email provided", location = 'json')
self.reqparse.add_argument('password', type = str, required = True, help = "No password provided", location = 'json')
self.reqparse.add_argument('role', type = bool, default = 0, location = 'json')
super(UserListAPI, self).__init__()
def get(self):
return { 'users': map(lambda u: marshal(u, user_fields), getAllUsers()) }
def post(self):
print self.reqparse.parse_args()
args = self.reqparse.parse_args()
new_user = User(args['name'], args['email'], args['password'], args['role'])
addUser(new_user)
return {'user' : marshal(new_user, user_fields)}, 201
api.add_resource(UserAPI, '/api/user/<int:id>', endpoint = 'user')
api.add_resource(UserListAPI, '/api/users/', endpoint = 'users')
if __name__ == "__main__":
app.run(debug=True)
И теперь я CURL это:
amegian@amegian-Ubuntu:~$ curl -H 'Content-Type: application/json' -X PUT -d '{"name": "test2", "email":"[email protected]", "password":"testpass", "role": 0}' http://127.0.0.1:5000/api/user/2 -v
* About to connect() to 127.0.0.1 port 5000 (#0)
* Trying 127.0.0.1... connected
> PUT /api/user/2 HTTP/1.1
> User-Agent: curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: 127.0.0.1:5000
> Accept: */*
> Content-Type: application/json
> Content-Length: 76
>
* upload completely sent off: 76out of 76 bytes
* HTTP 1.0, assume close after body < HTTP/1.0 200 OK < Content-Type: application/json < Content-Length: 39 < Server: Werkzeug/0.8.3 Python/2.7.3 < Date: Wed, 04 Dec 2013 21:08:40 GMT < {
"message": "You have PUT me" }
* Closing connection #0
Поэтому я бы посоветовал вам проверить те методы, которые я удалил... например checkUser (id)