How to use MQTT concept in FLASK REST API? - python

I have a requirement where will have a POST api call ,read the json data from this and publish the messages to this topic "/home/floor_1/room" before publishing need to connect to the broker also and then return a success response .
Project structure:
│ app.py
│ config.py
│ Dockerfile
│ requirement.txt
│
├───app_services
│ │ __init__.py
│ │
│ ├───controller
│ │ │ send_down_link.py
│ │ │ __init__.py
│ │
│ ├───models
│ │ │ __init__.py
│ │ │
│ │ ├───database
│ │ │ │ device.py
In app.py
from app_services import app
if __name__ == '__main__':
app.run(host=app.config['HOST'], port=app.config['PORT'], debug=app.config['DEBUG'])
in app_service/init.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_restful import Api
from flask_mqtt import Mqtt
from app_service.controller.send_down_link import SendDownlink
app = Flask(__name__)
db = SQLAlchemy(app)
mqtt = Mqtt(app)
api = Api(app)
api.add_resource(SendDownlink, "/api/t1/device/")
In controller/send_down_link.py:
class SendDownlink(Resource):
def post(self):
input_data = request.get_json()
message = input_data['message']
I want to publish this message to "/home/floor_1/room" topic . So i just want accommodate mqtt code in this 'post' method. Dont know how to work around it . Any suggestion ?

Given your stated goal is to just publish a message then the simplest way is to use the shortcut method provided by the Paho library that will handle all the connection and publication in a single call.
https://pypi.org/project/paho-mqtt/#publish-single-example
e.g.
import paho.mqtt.publish as publish
publish.single("home/floor_1/room", "payload", hostname="mqtt.eclipse.org")
p.s. Topics really shouldn't start with a leading /, it adds an unneeded null to the start of the topic tree and breaks things like Shared Subscriptions when you try and scale things later.

Related

Can I create a service in fastapi using an imported function from another .py file?

I have written some functions with python in separate files. My task is to transform these functions into services using fastAPI and the services should return a JSON that says if the operation is executed correctly or not (a code and a message).
For example, I have a file sum.py and inside there's a function that sums two numbers and returns the result:
def sum_of_two_numbers(a,b):
tot = a+b
return tot
Let's say I want to create a service using fastAPI, do you know if I can import sum_of_two_numbers from sum and use TestClient to complete this task without modyfing the code or re-writing it?
In this example the function is short, but have in mind my functions are different. I needed one month to write them all and make the connection to the Oracle db. While reading the documentation of fastAPI, I understood I should modify all the syntax to adapt it for fastAPI.
So, in short can I do this with fastAPI by simply importing the functions and without changing all the functions syntax? Or do you know if is there an easier way to do it?
In a basic fastapi app structure you often have something like this:
Example taken from Bastien-BO/fastapi-RBAC-microservice, inspired by Kludex/fastapi-microservices and tiangolo/full-stack-fastapi-postgresql
.
├── app
│ ├── __init__.py
│ ├── main.py
│ ├── dependencies.py
│ └── routers
│ │ ├── __init__.py
│ │ ├── items.py
│ │ └── users.py
│ └── models
│ │ ├── __init__.py
│ │ ├── items.py
│ │ └── users.py
│ └── schemas
│ │ ├── __init__.py
│ │ ├── items.py
│ │ └── users.py
│ └── internal
│ │ ├── __init__.py
│ │ └── crud
| | | └── user.py
| | | └── item.py
Often in your internal files you have functions or classes that you can serve with routes.
Example of a user route with internal db function call:
# app/routers/users.py
from app.internal.crud.user import crud_user
#router.get("/", response_model=List[UserOut])
async def read_users(offset: int = 0, limit: int = 100, session: Session = Depends(get_db)):
users = crud_user.get_multi(session, offset=offset, limit=limit)
return users
# app/internal/crud/user.py
def crud_user():
#do db stuff here
In this example, your sum_of_two_numbers function would be in the internal folder and you would wrap it in a route like what is done in read_users.
You should follow the user guide or the advanced user guide (fit better to your need i believe) from fastapi official doc. Also take a look at tiangolo (fastapi creator) Base Project Generator. You will have a good example on how to create a strong base for your API.

How to access APP properties inside my endpoint view function in FastAPI?

Here is my project structure:
│ .gitignore
│ README.md
│ requirements.txt
│ start.py
│
├───app
│ │ main.py
│ │
│ ├───apis
│ │ └───v1
│ │ │ __init__.py
│ │ │
│ │ │
│ │ ├───routes
│ │ │ │ evaluation_essentials.py
│ │ │ │ training_essentials.py
│ │ │
│ │
│ ├───models
│ │ │ request_response_models.py
│ │ │ __init__.py
│ │ │
This is what the outermost, start.py looks like:
import uvicorn
if __name__ == "__main__":
from fastapi import Depends, FastAPI
from app.apis.v1 import training_essentials, evaluation_essentials
app = FastAPI(
title="Some ML-API",
version="0.1",
description="API Contract for Some ML API",
extra=some_important_variable
)
app.include_router(training_essentials.router)
app.include_router(evaluation_essentials.router)
uvicorn.run(app, host="0.0.0.0", port=60096)
And, all my endpoints and viewfunctions have been created in training_essentials.py and evaluation_essentials.py
for example, this is what training_essentials.py looks like:
from fastapi import APIRouter
from fastapi import FastAPI, HTTPException, Query, Path
from app.models import (
TrainingCommencement,
TrainingCommencementResponse,
)
router = APIRouter(
tags=["Training Essentials"],
)
#router.post("/startTraining", response_model=TrainingCommencementResponse)
async def start_training(request_body: TrainingCommencement):
logger.info("Starting the training process")
## HOW TO ACCESS APP HERE?
## I WANT TO DO SOMETHING LIKE:
## some_important_variable = app.extra
## OR SOMETHING LIKE
## title = app.title
return {
"status_url": "some-status-url",
}
How do I access APP properties, its variables inside that viewfunction in my endpoint?
You can access the request.app as
from fastapi import Request
#router.post("something")
def some_view_function(request: Request):
fast_api_app = request.app
return {"something": "foo"}

Django - Determining how to split into apps based on functionality

Completely new to Django. I'm building a website where users can make profiles, search for other profiles, and view basic information.
I'm unsure about how to organize the apps. I want to following things on the navigation bar:
"About Us", "How it Works", "Join", "Login"
I know that users (join + login) will be its own app, but how would I bundle all of the information that will show up on the navigation bar? Will that just be one main app because it doesn't really do anything complex and really just presents text?
The concept of app in Django is that it does thing. For example if you are creating a website for school you have students as an app which manages students, an app for exams which only manages exams, grades etc. So your app should typically do one thing, if it does not break it down. The whole idea behind Django is having modular components which can act on their own.
In your case, what I would do is create an app called userapp. In userapp, I will have profile as a model containing username, password, fname, lname, picture, dob, hobbies etc.
On your home page, you can have separate flatpages for about us, how it works. These do not have to be app.
My project structure
├───.idea
├───firstapp
│ ├───migrations
│ │ └───__pycache__
│ └───__pycache__
├───myproj
│ └───__pycache__
├───secondapp
│ ├───migrations
│ │ └───__pycache__
│ └───__pycache__
├───static
│ ├───admin
│ │ ├───css
│ │ ├───fonts
│ │ ├───img
│ │ │ └───gis
│ │ └───js
│ │ ├───admin
│ │ └───vendor
│ │ ├───jquery
│ │ └───xregexp
│ ├───css
│ ├───fonts
│ ├───img
│ └───js
└───templates
└───firstapp

Should django templates name for each app be unique?

I'm developing a django app. It has three apps in it, each with it's own template directory and index.html file. But when I call view from the second app it picks up the template file from the first app rather than the second one.
Is it a must that every template name be unique?
my projects directory:
├───jobs
│ ├───migrations
│ ├───static
│ └───templates
├───job_portal
├───main_app
│ ├───migrations
│ ├───static
│ └───templates
├───project_static
│ ├───css
│ ├───fonts
│ ├───images
│ └───js
└───recruiters
├───migrations
├───static
│ ├───css
│ ├───fonts
│ ├───images
│ └───js
└───templates
In Django you can use templates with the same names for different apps. But you should add subfolders inside app's template directory like this:
my_app/templates/my_app/base.html
second_app/templates/second_app/base.html
Now in views you should include app name to the template name:
return render(request, 'my_app/base.html')
return render(request, 'second_app/base.html').

How to use app_context in Flask?

This is my structure. I have problem about implementing flask large application.
├─flasky
│ ├─app/
│ │ ├─templates/
│ │ ├─static/
│ │ ├─main/
│ │ │ ├─__init__.py
│ │ │ ├─errors.py
│ │ │ ├─forms.py
│ │ │ └─views.py
│ │ ├─__init__.py
│ │ ├─email.py
│ │ └─models.py
│ ├─migrations/
│ ├─tests/
│ │ ├─__init__.py
│ │ └─test*.py
│ ├─venv/
│ ├─requirements.txt
│ ├─config.py
│ └─manage.py
...
I encountered some problem When I was coding in email.py.
def send_email(to, subject, template, **kwargs):
msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject,
sender=app.config['FLASKY_MAIL_SENDER'], recipients=[to])
with the_app.app_context():
msg.body = render_template(template + '.txt', **kwargs)
msg.html = render_template(template + '.html', **kwargs)
thr = Thread(target=send_async_email, args=[app, msg])
thr.start()
return thr
def send_async_email(app, msg):
with app.app_context():
mail.send(msg)
I don't know how to call modules to implement the_app.app_context(). I hope that it can direct send_email function to get app/templates of location to be successful.
I found what the problem was. I needed to define a flask app in email.py:
import os
tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
the_app = Flask(__name__, template_folder=tmpl_dir)
I encountered a new problem with werkzeug.routing.BuildError, and I am searching for a solution. I found "Flask error: werkzeug.routing.BuildError" mentioned my problem.
werkzeug.routing.BuildError
BuildError: ('index', {}, None)
Because views.py had a typo arg of url_for(), I should type 'main.index'. It's right.
#main.route('/', methods=['GET', 'POST'])
def index():
form = NameForm()
if form.validate_on_submit():
...
return redirect(url_for('main.index'))
return render_template('index.html',
form=form, name=session.get('name'),
known=session.get('known', False),
current_time=datetime.utcnow())
But it can't enable the feature of sending email. I found "Python Flask Email KeyError KeyError: 'mail'" mentioned my problem. I needed to downgrade to flask_mail==0.9.0, which solved the problems.

Categories

Resources