Skip to content

Commit

Permalink
Merge pull request #81 from josemoracard/jose3-05-returning-json
Browse files Browse the repository at this point in the history
exercises 05-returning-json to 08.2-finish-todos
  • Loading branch information
tommygonzaleza authored Jan 11, 2024
2 parents 0389b22 + 9e099c9 commit c7f4571
Show file tree
Hide file tree
Showing 24 changed files with 115 additions and 120 deletions.
24 changes: 12 additions & 12 deletions .learn/exercises/05-returning-json/README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@

Las REST APIs tienen que retornar datos en formato JSON, no en formato HTML.

Puedes usar la función [flask jsonify](https://flask.palletsprojects.com/en/1.1.x/api/#flask.json.jsonify) para convertir con facilidad cualquier tipo de datos básico a JSON de esta forma:
Puedes usar la función [flask jsonify](https://flask.palletsprojects.com/en/3.0.x/api/#flask.json.jsonify) para convertir con facilidad cualquier tipo de datos básico a JSON de esta forma:

```python
# añade el método jsonify a tu importación de Flask
from flask import Flask, jsonify
# Añade el método jsonify a tu importación de Flask
from flask import Flask, jsonify

# supongamos que tienes tus datos en la variable some_data
some_data = { "name": "Bobby", "lastname": "Rixer" }
# Supongamos que tienes tus datos en la variable some_data
some_data = { "name": "Bobby", "lastname": "Rixer" }

@app.route('/blahblah', methods=['GET'])
@app.route('/myroute', methods=['GET'])
def hello_world():
# puedes convertir esa variable en una cadena json de la siguiente manera
# Puedes convertir esa variable en una cadena json de la siguiente manera
json_text = jsonify(some_data)

# y luego puedes devolverlo al front-end en el cuerpo de la respuesta de la siguiente manera
# Y luego puedes devolverlo al front-end en el cuerpo de la respuesta de la siguiente manera
return json_text
```

Si aplicamos estos conocimientos a nuestro proyecto de todo-list, podemos crear una variable global `todos` que va a contener la lista de todos de esta forma:
Si aplicamos estos conocimientos a nuestro proyecto de todo-list, podemos crear una variable global `todos` que va a contener la lista de todos de esta forma:

```python
todos = [
Expand All @@ -29,12 +29,12 @@ todos = [
]
```

## 📝 Instrucciones
## 📝 Instrucciones:

1. Crea una variable global todos, declárala globalmente. No la declares dentro de una función, declárala en cualquier lado pero a nivel global. Asegúrate de que la variable contenga por lo menos una tarea (task) con la siguiente estructura:
1. Crea una variable global `todos`, declárala globalmente. No la declares dentro de una función, declárala en cualquier lado pero a nivel global. Asegúrate de que la variable contenga por lo menos una tarea (task) con la siguiente estructura:

```python
{ "label": "My first task", "done": False }
[ { "label": "My first task", "done": False } ]
```

2. Cambia la función del endpoint de tu método GET para que retorne la versión en json (Usando jsonify) de la variable de `todos` recién creada.
21 changes: 10 additions & 11 deletions .learn/exercises/05-returning-json/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@

REST APIs have to return data in JSON format, not HTML format.

You can use the [flask jsonify](https://flask.palletsprojects.com/en/1.1.x/api/#flask.json.jsonify) function to easily convert any of the basic data-types to JSON data like this:
You can use the [flask jsonify](https://flask.palletsprojects.com/en/3.0.x/api/#flask.json.jsonify) function to easily convert any of the basic data-types to JSON data, like this:

```python
# Add the jsonify method to your Flask import
from flask import Flask, jsonify

# add the jsonify method to your Flask import
from flask import Flask, jsonify

# suppose you have your data in the variable named some_data
some_data = { "name": "Bobby", "lastname": "Rixer" }
# Suppose you have your data in the variable named some_data
some_data = { "name": "Bobby", "lastname": "Rixer" }

@app.route('/myroute', methods=['GET'])
def hello_world():
# you can convert that variable into a json string like this
# You can convert that variable into a json string like this
json_text = jsonify(some_data)

# and then you can return it to the front end in the response body like this
# And then you can return it to the front end in the response body like this
return json_text
```

If we apply this knowledge to our ToDo-list project, we can create a global variable named `todos` that will hold the list of todos like this:
If we apply this knowledge to our todo-list project, we can create a global variable named `todos` that will hold the list of todos like this:

```python
todos = [
Expand All @@ -30,12 +29,12 @@ todos = [
]
```

## 📝Instructions:
## 📝 Instructions:

1. Create a global variable called `todos`. Do not declare the variable inside any function. Declare the variable in the global scope and make sure the variable contains at least one task item (our task objects) inside with the following structure:

```python
[ { "label": "My first task", "done": False } ]
```

2. Change the function on the GET method's endpoint from string output so that it will return the jsonified version of the global variable `todos`.
2. Change the function on the GET method's endpoint from string output so that it will return the jsonified version of the global variable `todos`.
4 changes: 2 additions & 2 deletions .learn/exercises/05-returning-json/solution.hide.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
def hello_world():
return jsonify(todos)

# These two lines should always be at the end of your app.py file.
# These two lines should always be at the end of your app.py file
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3245, debug=True)
app.run(host='0.0.0.0', port=3245, debug=True)
8 changes: 4 additions & 4 deletions .learn/exercises/05-returning-json/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ def client():
os.close(db_fd)
os.unlink(app.config['DATABASE'])

@pytest.mark.it("folder src must exist")
@pytest.mark.it("Folder src must exist")
def test_src_folder():
assert os.path.isdir("./src/")

@pytest.mark.it("app.py must exist")
@pytest.mark.it("File app.py must exist")
def test_pipfile_exists():
assert os.path.isfile("src/app.py")

Expand Down Expand Up @@ -63,7 +63,7 @@ def test_labels_string():
if "label" in task:
assert isinstance(task["label"], str)

@pytest.mark.it('The value of the "done" key on each todo should be boolean')
@pytest.mark.it('The value of the "done" key on each todo should be a boolean')
def test_done_bool():
from src import app
for task in app.todos:
Expand All @@ -84,4 +84,4 @@ def test_return(client):

for task in _body:
assert "label" in task
assert "done" in task
assert "done" in task
2 changes: 1 addition & 1 deletion .learn/exercises/06-check-for-live/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# `06` Check the API

Now you can check your endpoint live in the browser. It should be returning the list of todos in JSON format like this:
Now you can check your endpoint live in the browser. It should be returning the list of todos in JSON format, like this:

![check live todos](../../assets/return_todos.gif?raw=true)
21 changes: 9 additions & 12 deletions .learn/exercises/07-post_todo/README.es.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# `07` POST /todos (añade un nuevo task)
# `07` POST /todos (add a new task)

Ahora que ya está hecho el método GET `/todos`, debemos pensar en el resto de los endpoints de nuestra API:

Expand All @@ -8,26 +8,23 @@ POST /todos
DELETE /todos
```

Para poder construir el `POST /todos` debemos hacer algo similar a lo que hicimos en el primer endpoint, recuerda que cada endpoint en una Flask API está representada por una función y decorador como este:
Para poder construir el `POST /todos` debemos hacer algo similar a lo que hicimos en el primer endpoint, recuerda que cada endpoint en una Flask API está representada por una función y un decorador de esta manera:

```python
@app.route('/blabla', methods=['GET'])
@app.route('/myroute', methods=['GET'])
def hello_world():
return 'Hello, World!'
return 'Hello World!'
```

Pero en este caso no esperaremos una solicitud `GET`.
Pero en este caso no esperaremos una solicitud `GET`, sino una solicitud `POST`.

También, esperamos recibir el `todo` (tarea) que el cliente quiere añadir dentro del `request_body` (cuerpo de la solicitud), solo que en este caso, no esperaremos una `request`(solicitud) `GET`.

Esperamos recibir el `todo` que el cliente desea añadir dentro del `request_body`.
También, esperamos recibir el TODO que el cliente quiere añadir dentro del `request_body` (cuerpo de la solicitud).

```python
from flask import request

# el request_body o cuerpo de la solicitud ya fue decodificado por json y se encuentra en la variable request.data

print(request.data)
# El request_body o cuerpo de la solicitud ya está decodificado en formato JSON y se encuentra en la variable request.json
print(request.json)
```

## 📝 Instrucciones:
Expand All @@ -37,7 +34,7 @@ print(request.data)
```python
@app.route('/todos', methods=['POST'])
def add_new_todo():
request_body = request.data
request_body = request.json
print("Incoming request with the following body", request_body)
return 'Response for the POST todo'
```
Expand Down
24 changes: 13 additions & 11 deletions .learn/exercises/07-post_todo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ POST /todos
DELETE /todos
```

In order to build the `POST /todos` endpoint, we have to do something similar to what we did in the first endpoint with our GET method. Remember that each endpoint in a Flask API is represented by a function ( def my_function(): ) and a decorator ( @app.route() ) like this:
In order to build the `POST /todos` endpoint, we have to do something similar to what we did in the first endpoint with our GET method. Remember that each endpoint in a Flask API is represented by decorator and a function, like this:

```python
@app.route('/myroute', methods=['GET'])
def hello_world():
return 'Hello, World!'
return 'Hello World!'
```

In this case, we are not going to be expecting a `GET` request, but rather a `POST` request.
Expand All @@ -23,24 +23,26 @@ Also, we are expecting to receive the TODO that the client wants to add inside o
```python
from flask import request

# the request body is already json decoded and it comes in the request.json variable
# The request body is already JSON decoded, and it comes in the request.json variable
print(request.json)
```

## 📝 Instructions:

1. Remember to import `request` at the top of the file:

```python
from flask import request
```

2. Then, Add the folowing endpoint to your app.py and test it:
1. Add the following endpoint to your `app.py` and test it:

```python
@app.route('/todos', methods=['POST'])
def add_new_todo():
request_body = request.data
request_body = request.json
print("Incoming request with the following body", request_body)
return 'Response for the POST todo'
```

2. Remember to import `request` at the top of the file:

```python
from flask import request
```


6 changes: 3 additions & 3 deletions .learn/exercises/07-post_todo/solutions.hide.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ def hello_world():

@app.route('/todos', methods=['POST'])
def add_new_todo():
request_body = request.data
request_body = request.json
print("Incoming request with the following body", request_body)
return 'Response for the POST todo'


# These two lines should always be at the end of your app.py file.
# These two lines should always be at the end of your app.py file
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3245, debug=True)
app.run(host='0.0.0.0', port=3245, debug=True)
6 changes: 3 additions & 3 deletions .learn/exercises/07-post_todo/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ def client():
os.close(db_fd)
os.unlink(app.config['DATABASE'])

@pytest.mark.it("folder src must exist")
@pytest.mark.it("Folder src must exist")
def test_src_folder():
assert os.path.isdir("./src/")

@pytest.mark.it("app.py must exist")
@pytest.mark.it("File app.py must exist")
def test_pipfile_exists():
assert os.path.isfile("src/app.py")

Expand Down Expand Up @@ -63,7 +63,7 @@ def test_labels_string():
if "label" in task:
assert isinstance(task["label"], str)

@pytest.mark.it('The value of the "done" key on each todo should be boolean')
@pytest.mark.it('The value of the "done" key on each todo should be a boolean')
def test_done_bool():
from src import app
for task in app.todos:
Expand Down
2 changes: 1 addition & 1 deletion .learn/exercises/07.1-test-post-todo/README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Hasta ahora esto lo que tienes sobre el endpoint `POST /todos`, tomate el tiempo
```python
@app.route('/todos', methods=['POST'])
def add_new_todo():
request_body = request.data
request_body = request.json
print("Incoming request with the following body", request_body)
return 'Response for the POST todo'
```
Expand Down
6 changes: 3 additions & 3 deletions .learn/exercises/07.1-test-post-todo/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ def client():
os.close(db_fd)
os.unlink(app.config['DATABASE'])

@pytest.mark.it("folder src must exist")
@pytest.mark.it("Folder src must exist")
def test_src_folder():
assert os.path.isdir("./src/")

@pytest.mark.it("app.py must exist")
@pytest.mark.it("File app.py must exist")
def test_pipfile_exists():
assert os.path.isfile("src/app.py")

Expand Down Expand Up @@ -63,7 +63,7 @@ def test_labels_string():
if "label" in task:
assert isinstance(task["label"], str)

@pytest.mark.it('The value of the "done" key on each todo should be boolean')
@pytest.mark.it('The value of the "done" key on each todo should be a boolean')
def test_done_bool():
from src import app
for task in app.todos:
Expand Down
22 changes: 10 additions & 12 deletions .learn/exercises/07.2-finish-post-todo/README.es.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
# `07.2` Finish the POST /todos

Ahora... si queremos terminar el post, tenemos que realizar estas acciones específicas:

+ Primero asegúrate de convertir el cuerpo de la solicitud en una estructura de datos real de Python, como un diccionario. Ya usamos `request.json` para eso, ya que sabemos que la solicitud estará en formato application/json. Si eso no se conoce, es posible que desee usar `request.get_json(force=True)` para ignorar el tipo de contenido y tratarlo como json.

+ Agrega el diccionario a la lista de `todos`.

+ Devuelve la nueva lista de `todos`.

Tu código debería verse así ahora:

```python

@app.route('/todos', methods=['POST'])
def add_new_todo():
request_body = request.json
print("Incoming request with the following body", request_body)
return 'Response for the POST todo'

```

Obviamente, este punto final actualmente no agrega nada nuevo a nuestra 'base de datos' (la lista `todo`).
Ahora... si queremos terminar el post, tenemos que realizar estas acciones específicas:

+ Primero asegúrate de convertir el cuerpo de la solicitud en una estructura de datos real de Python, como un diccionario. Ya usamos `request.json` para eso, ya que sabemos que la solicitud estará en formato `application/json`. Si el formato no se conoce, es posible que deba usar `request.get_json(force=True)` para ignorar el tipo de contenido y tratarlo como json.

+ Agrega el diccionario a la lista de `todos`.

+ Devuelve la nueva lista de `todos`.

Obviamente, este punto final actualmente no agrega nada nuevo a nuestra 'base de datos' (la lista `todos`).

Completemos el código para que el punto final pueda hacer tu trabajo: agregar una nueva tarea a los `todos`.

Expand All @@ -30,4 +28,4 @@ Completemos el código para que el punto final pueda hacer tu trabajo: agregar u

2. Devuelve la lista actualizada `todos` al front end.

3. No olvide `jsonify` su devolución. ¿Por qué es esto necesario? Discuta con la clase.
3. No olvide hacer `jsonify` en lo que devuelve. ¿Por qué es esto necesario? Discuta con la clase.
7 changes: 3 additions & 4 deletions .learn/exercises/07.2-finish-post-todo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
Your code should look like this by now:

```python

@app.route('/todos', methods=['POST'])
def add_new_todo():
request_body = request.json
Expand All @@ -13,13 +12,13 @@ def add_new_todo():

Now... if we want to finish our `POST` method, we have to perform the following specific actions:

+ First: Make sure that you are converting the request body into a real python data structure, like a dictionary. You can see that we already used `request.json` for that since we know the request will be in application/json. However, if that is not known, you may want to use `request.get_json(force=True)` to ignore the content type and treat it like json.
+ First: Make sure that you are converting the request body into a real Python data structure, like a dictionary. You can see that we already used `request.json` for that since we know the request will be in `application/json`. However, if that is not known, you may want to use `request.get_json(force=True)` to ignore the content type and treat it like json.

+ Second: Add the dictionary into the list of `todos`.

+ Last: Return the new list of `todos`.

Currently, this endopint is not adding anything new to our 'database' (the `todo` list).
Currently, this endpoint is not adding anything new to our 'database' (the `todos` list).

Let's complete our code so the endpoint can do its job - add a new task to the `todos` list.

Expand All @@ -30,4 +29,4 @@ Let's complete our code so the endpoint can do its job - add a new task to the `

2. Return the updated list `todos` to the front end.

3. Do not forget to `jsonify` your return. Why is this necessary? Ask instructor to discuss with the class.
3. Do not forget to `jsonify` your return. Why is this necessary? Ask the instructor to discuss this with the class.
Loading

0 comments on commit c7f4571

Please sign in to comment.