discentes-imd / IntegraTI-API

API RESTful para o projeto IntegraTI
https://api-integrati.herokuapp.com/
GNU General Public License v3.0
6 stars 0 forks source link

Rotas da api e swagger #15

Open felihenrique opened 7 years ago

felihenrique commented 7 years ago

Para facilitar na implementação, creio que seria bom definirmos primeiramente quais rotas fazem o quê, seguindo o padrão: GET para obter informações, POST para criar um novo recurso, PUT para editar um recurso e DELETE para remover um recurso. Ex: GET /events?page=x&pagesize=x - Retorna lista de eventos. Alguns parametros podem ser passados na url para definir quais eventos retornar como: intervalo de datas, quantidade de eventos, inicio da seleção, etc.. GET /events/{id} - Retorna informações sobre um evento em específico. POST /events/ - Cria um novo evento. O evento deve estar no corpo da request em forma de json. PUT /events/{id} - Edita um evento existente. O evento editado deve estar no corpo da request em forma de json. DELETE /events/{id} - Deleta um evento em específico.

Edit: Precisa também colocar as possíveis respostas do servidor.

rodrigondec commented 7 years ago

Um adendo sobre o:

POST /events/ - Cria um novo evento. O evento deve estar no corpo da request em forma de json.

Será enviado um arquivo também pelo post na criação do evento.

rodrigondec commented 7 years ago

Outro adendo, sobre:

DELETE /events/{id} - Deleta um evento em específico.

A ação de deletar no nosso sitema irá apenas desabilitar o registro. Colocarei o campo 'active'/'enabled' nas entidades.

felihenrique commented 7 years ago

Porque apenas desabilita?

rodrigondec commented 7 years ago

É uma boa prática, foi sugerido por @davidcardoso-ti e discutido na última reunião. Nunca é bom deletar mesmo o registro. Pois se o delete tiver sido um erro humano ou não, pode ser revertido. E não perdemos um database de conhecimento.

felihenrique commented 7 years ago

Em relação a enviar arquivo, é bom ter uma rota apenas para dar upload de arquivos no servidor e retornar a url que foi armazenado o arquivo. Essa url coloca no evento que vai mandar no POST, que é o que vai ser armazenado de fato no db.

rodrigondec commented 7 years ago

Então isso ficará num controller do front. Forneceremos uma url pra registrar o evento e uma url pra registrar o arquivo. E o controller do front terá que chamar essas duas url, correto?

felihenrique commented 7 years ago

Isso. Apos dar o upload do arquivo, o front coloca a url no json e faz a solicitação POST.

felihenrique commented 7 years ago

Isso evitaria duplicações em outras coisas que precisarão enviar arquivos.

rodrigondec commented 7 years ago

sim, verdade. Esqueci que arquivo não era mais acoplado a evento. Nice

rodrigondec commented 7 years ago

@felihenrique Se a gente deixar dessa forma sem a parametrização do id na url e utilizar a forma 'padrão' de get, ficando dessa forma a utilização da url image

rodrigondec commented 7 years ago

Outra coisa que eu vi, é utilizado um controler pra a entidade, e um controle pra lista de entidades, como no exemplo:


from flask.ext.restplus import Api, Resource, fields

app = Flask(__name__)
api = Api(app, version="1.0", title="Todo API",
    description="A simple TODO API extracted from the original flask-restful example",
)

ns = api.namespace("todos", description="TODO operations")

TODOS = {
    "todo1": {"task": "build an API"},
    "todo2": {"task": "?????"},
    "todo3": {"task": "profit!"},
}

todo = api.model("Todo", {
    "task": fields.String(required=True, description="The task details")
})

listed_todo = api.model("ListedTodo", {
    "id": fields.String(required=True, description="The todo ID"),
    "todo": fields.Nested(todo, description="The Todo")
})

def abort_if_todo_doesnt_exist(todo_id):
    if todo_id not in TODOS:
        api.abort(404, "Todo {} doesn"t exist".format(todo_id))

parser = api.parser()
parser.add_argument("task", type=str, required=True, help="The task details", location="form")

@ns.route("/<string:todo_id>")
@api.doc(responses={404: "Todo not found"}, params={"todo_id": "The Todo ID"})
class Todo(Resource):
    '''Show a single todo item and lets you delete them'''
    @api.doc(description="todo_id should be in {0}".format(", ".join(TODOS.keys())))
    @api.marshal_with(todo)
    def get(self, todo_id):
        '''Fetch a given resource'''
        abort_if_todo_doesnt_exist(todo_id)
        return TODOS[todo_id]

    @api.doc(responses={204: "Todo deleted"})
    def delete(self, todo_id):
        '''Delete a given resource'''
        abort_if_todo_doesnt_exist(todo_id)
        del TODOS[todo_id]
        return "", 204

    @api.doc(parser=parser)
    @api.marshal_with(todo)
    def put(self, todo_id):
        '''Update a given resource'''
        args = parser.parse_args()
        task = {"task": args["task"]}
        TODOS[todo_id] = task
        return task

@ns.route("/")
class TodoList(Resource):
    '''Shows a list of all todos, and lets you POST to add new tasks'''
    @api.marshal_list_with(listed_todo)
    def get(self):
        '''List all todos'''
        return [{"id": id, "todo": todo} for id, todo in TODOS.items()]

    @api.doc(parser=parser)
    @api.marshal_with(todo, code=201)
    def post(self):
        '''Create a todo'''
        args = parser.parse_args()
        todo_id = "todo%d" % (len(TODOS) + 1)
        TODOS[todo_id] = {"task": args["task"]}
        return TODOS[todo_id], 201

if __name__ == "__main__":
    app.run(debug=True)```
felihenrique commented 7 years ago

Não sei.. Acho que não precisa mudar, pq quando for passar outros parametros não vai ser passado o id.

Para lista é outro controller mesmo, pq cada classe só pode ter um método get, python não tem sobrecarga de funções :P

felihenrique commented 7 years ago

No caso seguindo a logica desse codigo ai, poderia coloca para listar na classe EventPostController, e mudar o nome da classe.

rodrigondec commented 7 years ago

Sim, gostei dessa segunda abordagem que coloquei ai