Fetching Data and Integrating APIs with Zenaura
Zenaura simplifies the process of fetching data from APIs and integrating it into your Python-based web applications.
Key Concepts
-
Async/Await: Zenaura embraces asynchronous programming for efficient data fetching.
async def
functions allow your application to perform other tasks while waiting for API responses. -
mutator
: Themutator
decorator is used to mark functions that modify component state. This ensures the component automatically re-renders to reflect the updated data.
Example Client-Side Component (DataFetcher
)
Create zenaura application
Add requests to config.json
Presentational components
from zenaura.ui import div, img, h1, p
def Div(class_name, children):
return div(*children, class_=class_name)
def Image(src, alt, width, height, classname=""):
return img(
src=src,
alt=alt,
width=width,
height=height,
class_=classname
)
def Header1(text):
return h1(text)
def Paragraph(text):
return p(text)
def Spinner(text):
return Div("spinner-container", [
Header1(text),
])
def LoadingComponent():
"""Displays a loading indicator while data is being fetched."""
return Div("loading", [
Spinner("spinner"), # Replace 'Spinner' with your actual spinner component
Paragraph("Loading data...")
])
def ErrorComponent(error):
"""Displays an error message when data fetching fails."""
return Div("error", [
Image("./public/error.png", "error", "45", "45"),
Header1("Error Fetching Data"),
Paragraph(error)
])
main component
from zenaura.client.component import Component
from zenaura.client.mutator import mutator
from public.presentational import *
import requests
def DataDisplayComponent(data):
return Div("data-dict", [
Div("item", [Paragraph(key), Paragraph(str(value))])
for key, value in data.items()
])
class DataFetcher(Component):
def __init__(self):
super().__init__()
self.state = {"data": None, "error": None} # Initial state
async def fetch_data(self):
try:
api_url = 'https://randomuser.me/api/' # Your API endpoint
response = requests.get(api_url)
if response.ok:
self.state["data"] = response.json()
else:
self.state["error"] = "API request failed"
except Exception as e:
self.state["error"] = str(e)
@mutator
async def attached(self):
await self.fetch_data()
print(self.state["data"])
def render(self):
if self.state["error"]:
return ErrorComponent(error=self.state["error"])
elif self.state["data"]:
return DataDisplayComponent(data=self.state["data"])
else:
return LoadingComponent()
Build and run zenaura app
now if we went to http://localhost:5000, and open the console we will see this
{
"results": [
{
"gender": "male",
"name": {
"title": "Mr",
"first": "Charles",
"last": "Clark"
},
"location": {
"street": {
"number": 5328,
"name": "Vimy St"
},
"city": "Grand Falls",
"state": "Nunavut",
"country": "Canada",
"postcode": "Z1S 2U2",
"coordinates": {
"latitude": "-69.8976",
"longitude": "-134.5780"
},
"timezone": {
"offset": "-6:00",
"description": "Central Time (US & Canada), Mexico City"
}
},
"email": "charles.clark@example.com",
"login": {
"uuid": "3338f687-3461-4a72-88e9-33eb19c9077d",
"username": "tinymeercat320",
"password": "kang",
"salt": "mrAgPCkY",
"md5": "1e1006b14c2e083026c86c129be8c0b8",
"sha1": "e29949ab4b75c8fa07b79312098e28edb7e10e27",
"sha256": "e3f3e1ffcf4e73ece750f437f70ac840a941b154e002a5d7327ee84111f59230"
},
"dob": {
"date": "1957-01-26T13:12:12.937Z",
"age": 67
},
"registered": {
"date": "2020-10-19T19:29:09.124Z",
"age": 3
},
"phone": "C57 P04-4851",
"cell": "R98 P02-7749",
"id": {
"name": "SIN",
"value": "389514100"
},
"picture": {
"large": "https://randomuser.me/api/portraits/men/70.jpg",
"medium": "https://randomuser.me/api/portraits/med/men/70.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/men/70.jpg"
},
"nat": "CA"
}
],
"info": {
"seed": "61b28009e82e3240",
"results": 1,
"page": 1,
"version": "1.4"
}
}
Explanation
- State: The
state
dictionary holds the fetched data (data
) and any potential error messages (error
). fetch_data
: Thisasync
function handles the API request usingrequests
.data
&error
: update the state based on the API response or error.attached
: Automatically fetches data when the component is added to the DOM, and re-render the component with the data.
In all, this component will set data to data state, error to error if error exists, it uses python requests library to fetch requests, and on success renders an error or data.
Key Improvements
- Clearer structure and separation of concerns.
- Error handling mechanism.
- Flexibility to use different state management approaches.