Как получить ID из URL для Put route и Delete - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь поместить все методы crud в один класс обработчика в python Tornado framework. Post() и get() работает, но по какой-то причине carId не может быть определен. Каким образом я могу передать идентификатор конечной точки API в метод. конечная точка для установки и удаления: api/cars/1

Ошибка: Ошибка типа: put () отсутствует 1 обязательный позиционный аргумент:
'carId' ОШИБКА: tornado.access: 500 PUT / api / cars / 1 (:: 1) 0,50 мс

Методы:

    # Delete method that deletes data specified by HTTP client from database
    def delete(self, carId):

        try:
            data = json.loads(self.request.body)
            print(data)
            print("Deleting Car")
            id = data["id"]
            if not carId:
                return self.write({"success": False})
            if not len(id):
                return self.write({"success": False})
            c.execute(
                "DELETE FROM cars WHERE id=?",(carId))
            self.write({"success": 200})
        except:
            self.write({"success": False})
        conn.commit()

    # Put route to edit an entity in DB.
    def put(self, carId):

        try:
            data = json.loads(self.request.body)
            print(data)
            print("Updating Cars table")
            id = data["id"]
            make = data["make"]
            model = data["model"]
            if not make or not model or not carId:
                return self.write({"success": False})
            if not len(make) or not len(model):
                return self.write({"success": False})
            c.execute(
                "UPDATE cars SET make=?, model=? WHERE id=?",(make, model, id))
            self.write({"success": 200})
        except:
            self.write({"success": False})
        conn.commit()


def verifyDatabase():
    try:
        c.execute('SELECT * FROM cars')
        print('Table already exists')
    except:
        print('Creating table \'cars\'')
        c.execute('CREATE TABLE cars (\
            id integer primary key,\
            make text,\
            model text)')
        print('Successfully created table \'cars\'')
    conn.commit()

class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/", MainHandler),
            (r"/api/cars/?", CarHandler),
            (r"/api/cars/[0-9]/?", CarHandler)
        ]
        tornado.web.Application.__init__(self, handlers)

def main():

    # Verify the database exists and has the correct layout
    verifyDatabase()

    app = Application()
    app.listen(80)
    IOLoop.instance().start()
    conn.close()
if __name__ == '__main__':
    main()

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Объясняя ошибку : Этот маршрут (r"/api/cars/?", CarHandler) указывает на CarHandler, но не передает аргументов методам обработчика. Я считаю, что методы get и post определены следующим образом: def get(self):, поэтому им действительно не нужно никаких аргументов; С другой стороны, методы put и delete определены как def put(self, carId):, поэтому им необходимо получить аргумент. По этой причине вы получили ошибку: Error: TypeError: put() missing 1 required positional argument: Точно так же, (r"/api/cars/[0-9]/?", CarHandler) тоже не передает аргументов.

Исправление ошибки маршрута : Во-первых, как объяснил другой член, вам нужно исправить (r"/api/cars/[0-9]/?", CarHandler), чтобы передать аргумент вашим методам. Вы можете сделать это, просто набрав ( и ) в вашем маршруте. Должно быть так: (r"/api/cars/([0-9])/?", CarHandler).

Исправление ошибки определения метода : Вы можете видеть, что даже если вы делаете то, что я сказал, вы, вероятно, все еще получаете ту же ошибку. Проблема в том, что все маршруты указаны для всех методов в обработчике. Таким образом, методы обработчика должны иметь одинаковую сигнатуру метода, или они должны иметь возможность вызываться одинаково.

Этот момент немного хитрый. Методы PUT и DELETE ожидают получения carId , но не все маршруты передают carId в качестве аргумента ((r"/api/cars/?", CarHandler) нет). Этот маршрут вызывает методы следующим образом: self.method(); он будет работать с self.get() или self.post(), но не будет помещен или удален, если они ожидают аргумента. Вы можете исправить это, разделив ваш обработчик на две части или изменив определение метода на:

def delete(self, carId=None):
    ...

def put(self, carId=None):
    ...

И добавление некоторой логической проверки как if carId is None: return

0 голосов
/ 29 апреля 2018

Вам необходимо использовать группу захвата в регулярном выражении, чтобы сообщить Tornado, какие части передать вашим методам. Поставьте скобки вокруг части, соответствующей carId:

 (r"/api/cars/([0-9])/?", CarHandler)

Обратите внимание, что carId будет передано как строка, поэтому вам может потребоваться преобразовать ее в carId = int(carId). (Кроме того, если ваши автомобильные идентификаторы не будут состоять из одной цифры, вы, вероятно, захотите вместо ([0-9]+))

...