fast api depends SQL connection - python

I'm new in fast api. I'm trying to get user from my table but getting this error:
user = await db.query(User).filter(User.login == data['login']).first()
AttributeError: 'Depends' object has no attribute 'query'
here is my server/database.py
import os
from sqlmodel import SQLModel, Session
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = os.environ.get("DATABASE_URL")
engine = create_async_engine(DATABASE_URL, echo = True, future = True)
async def init_db():
async with engine.begin() as conn:
# await conn.run_sync(SQLModel.metadata.drop_all)
await conn.run_sync(SQLModel.metadata.create_all) # init is ok, db table working
pass
async def get_session() -> AsyncSession:
async_session = sessionmaker(
engine, class_ = AsyncSession,
expire_on_commit = False
)
async with async_session() as session:
yield session
here is server/web_server.py
from fastapi import Depends, FastAPI
from sqlalchemy.future import select
from fastapi_socketio import SocketManager
from fastapi_login import LoginManager
import json
from database import get_session, init_db
from models import User, File
app = FastAPI()
sio = SocketManager(app = app)
#app.on_event("startup")
async def on_startup():
await init_db() # is ok
#app.sio.on('connect')
async def handle_connect(sid, connection_data):
await app.sio.emit('connect', 'User joined') # is ok
#app.sio.on('authorize')
async def authorize(sid, message, db = Depends(get_session)):
data = json.loads(message) # is ok
user = await db.query(User).filter(User.login == data['login']).first() # error in this line
print(user)
if __name__ == '__main__':
import uvicorn
uvicorn.run("web_server:app", host = '0.0.0.0', port = 8000, reload = True, debug = False)
I'm using socketio for my app, socketio.on('authorize') message contains data = {'login' : '...', 'password' : '...'} and I want to use this to find user in my postgresql table to check password and authorize it. So having problems with 'get_session', query, execute and commit not working with it, getting the same error AttributeError: 'Depends' object has no attribute ...

Related

Tornado Framework - how to use Handlersrequest to call an asynchronous function

This is a Python code for a Tornado web application. The code defines two classes, BaseHandler and MainHandlerIndex, both of which inherit from the Tornado web library's RequestHandler. The BaseHandler class has a method, "get_username_id_get_data", which returns the username ID obtained from a "get_data" module. The MainHandlerIndex class has a "get" method decorated with the "#decoradores.authenticated" and "#gen.coroutine" decorators, which handles incoming GET requests. This method retrieves the username cookie, obtains the username ID using the "get_username_id_get_data" method, and then renders an HTML template "index/index.html" with the title, items, username, and version as variables.
import tornado.web
from tornado import gen
from functools import wraps
import modulos.decoradores as decoradores
import modulos.get_data as get_data
import logging
logging.basicConfig(level=logging.DEBUG)
import tracemalloc; tracemalloc.start()
class BaseHandler(tornado.web.RequestHandler):
async def get_username_id_get_data(self):
print("soy basehandler y estoy siendo ejecutado....")
username_id = await get_data.primero_redis_segundo_query("user", "('username', '=', 'test')", 'x')
print("get_username_id_get_data: ", username_id)
return username_id
class MainHandlerIndex(BaseHandler):
#decoradores.authenticated
#gen.coroutine
async def get(self):
print("Iniciando MainHandlerIndex metodo: GET")
username_cookie_pre = self.get_secure_cookie("user")
username_cookie = username_cookie_pre.decode()
#username_cookie = 'test'
username_id = await self.get_username_id_get_data()
version = self.application.settings['valores_entorno']['version']
print("###########################################################################")
print("00_username_cookie------------>",username_cookie )
print("11_username_id------------>",username_id )
print("22_version------------>",version )
print("###########################################################################")
items_test = ["Item 1_index", "Item 2_index", "Item 3_index"]
#items_test = []
self.render("index/index.html", title="test", items=items_test, username=str(username_cookie).strip("\""), version=version)
This is the contents of the file index.py:
import asyncio
import os
import tornado.web
#----------------------------#
# Definir entorno #
#----------------------------#
from config import Settings, PreProductionSettings, ProductionSettings
import tornado.options
tornado.options.parse_config_file('config.py')
valores_entorno = PreProductionSettings()
#print(tornado.options.options.version)
#----------------------------#
# Handlers from modules #
#----------------------------#
from blueprints.test.handlers import MainHandlerTest #TEST <-- Borrar....from blueprints.index.handlers import MainHandlerIndex #Index
from blueprints.rid_propios.ri_handlers import MainHandlerRid_Propio_Index #Remote_id_propios
from blueprints.login.login_handlers import MainHandlerLogin, LogoutHandler, RegisterHandler, ConfirmeHandler
from blueprints.index.handlers import MainHandlerIndex
#----------------------------#
# Módulos del proyecto #
#----------------------------#
import modulos.gestiondb as gestiondb
import modulos.redis_stack as redisstack
import modulos.tablas as Tablas
from aiopg.sa import create_engine
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print("BASE_DIR: ", BASE_DIR)
engine = create_engine(
user=tornado.options.options.user,
database=tornado.options.options.database,
host=tornado.options.options.host,
password=tornado.options.options.password,
)
def make_app():
settings = {
"template_path": os.path.join(os.path.dirname(__file__), "templates"), #/home/developer/xrig_torado/web/web/blueprints/base/templates
"blueprints_path": os.path.join(os.path.dirname(__file__), "web/blueprints"), #/home/developer/xrig_torado/web/web/blueprints
"static_path": os.path.join(os.path.dirname(__file__), "static"), #/home/developer/xrig_torado/web/static
"cookie_secret": tornado.options.options.cookie_secret,
"login_url": "/login",
"xsrf_cookies": True,
"valores_entorno": tornado.options.options
}
handlers = (
(r'/', MainHandlerIndex),
(r'/login', MainHandlerLogin),
(r'/logout', LogoutHandler),
(r'/register', RegisterHandler),
(r'/confirmar', ConfirmeHandler),
(r'/test', MainHandlerTest),
(r'/rid_propios_index', MainHandlerRid_Propio_Index)
)
return tornado.web.Application(
handlers,
debug = True,
autoreload = True,
**settings,
#db = db
db_engine = engine,
)
async def main():
app = make_app()
app.listen(tornado.options.options.puerto_xrig)
#await asyncio.Event().wait()
await asyncio.Event().wait()
print(f'🌐 Server is listening on localhost on port {tornado.options.options.puerto_xrig}')
#Comprobando que existen la tablas del proyecto:
db_dsn = tornado.options.options.dsn
#lista_tablas = [gestiondb.tbl_benchmark, gestiondb.alpha, gestiondb.user, ]
lista_tablas = [Tablas.tbl_benchmark, Tablas.alpha, Tablas.user, Tablas.rid, Tablas.rid_propio ]
await gestiondb.rutina_alta_db_proyecto(db_dsn, lista_tablas)
#Comprobaciones Redis Stack.
await redisstack.lista_tablas_para_volcar_en_redis()
shutdown_event = asyncio.Event()
await shutdown_event.wait()
if __name__ == "__main__":
asyncio.run(main())
The extension starts correctly, does the login process and once the authenticated user is when I make a redirect to the root path / (this is where I can not operate a code that can call asynchronous functions). I have tried to follow several examples and there is no way the error is always:
http://http://192.168.196.49:8888/ (depués del proceso login)
[I 230205 19:48:57 web:2271] 200 GET / (192.168.196.4) 14.50ms
/usr/lib/python3.9/asyncio/events.py:80: RuntimeWarning: coroutine 'MainHandlerIndex.get' was never awaited
self._context.run(self._callback, *self._args)
Object allocated at (most recent call last):
File "/home/developer/xrig_torado/lib/python3.9/site-packages/tornado/gen.py", lineno 216
result = ctx_run(func, *args, **kwargs)
[W 230205 19:48:57 web:2271] 404 GET /favicon.ico (192.168.196.4) 7.46ms
I do NOT find enough documentation that explains an architecture to do this kind of thing. The intention is in the requestHandler in the GET or POST method to develop code and be able to call asynchronous functions.

WebSocket connection is not return any data?

I run this code the handshake and connection work fine but I don't get any results after I run the client.even though the code is working perfectly without any issues.
is there any idea to fix the problem?
note: I'm using graphql and Django framework in my project
import asyncio
import graphene
from channels.routing import ProtocolTypeRouter, URLRouter
class Query(graphene.ObjectType):
hello = graphene.String()
#staticmethod
def resolve_hello(obj, info, **kwargs):
return "world"
class Subscription(graphene.ObjectType):
"""Channels WebSocket consumer which provides GraphQL API."""
count_seconds = graphene.Float()
async def resolve_count_seconds(root, info):
for i in range(10):
yield i
await asyncio.sleep(1.)
schema = graphene.Schema(query=Query, subscription=Subscription)
class MyGraphqlWsConsumer(channels_graphql_ws.GraphqlWsConsumer):
"""Channels WebSocket consumer which provides GraphQL API."""
schema = schema
async def on_connect(self, payload):
pass
application = channels.routing.ProtocolTypeRouter({
"websocket": channels.routing.URLRouter([
django.urls.path("graphql/", MyGraphqlWsConsumer.as_asgi()),
])
})
ASGI_APPLICATION = 'graphql_ws.urls.application'
client:
from graphql_client import GraphQLClient
ws = GraphQLClient('ws://localhost:8000/graphql/')
def callback(_id, data):
print("got new data..")
print(f"msg id: {_id}. data: {data}")
query = """
subscription {
countSeconds
}
"""
sub_id = ws.subscribe(query, callback=callback)

Cache or Reuse Mongodb connection in AWS lambda using Python

I'm building a serverless application using Python and Mongodb. In documentation I found that I need to write db connection outside handler function. I have used Mangum python package as adapter to handle API gateway.
from fastapi import FastAPI, Body, status, Depends
from mangum import Mangum
from motor.motor_asyncio import AsyncIOMotorClient
from fastapi.responses import JSONResponse
from app.utility.config import MONGODB_URL, MAX_CONNECTIONS_COUNT, MIN_CONNECTIONS_COUNT, MAX_DB_THREADS_WAIT_COUNT, MAX_DB_THREAD_QUEUE_TIMEOUT_COUNT
application= FastAPI()
client = AsyncIOMotorClient(str(MONGODB_URL),
maxPoolSize=MAX_CONNECTIONS_COUNT,
minPoolSize=MIN_CONNECTIONS_COUNT,
waitQueueMultiple = MAX_DB_THREADS_WAIT_COUNT,
waitQueueTimeoutMS = MAX_DB_THREAD_QUEUE_TIMEOUT_COUNT )
async def get_database() -> AsyncIOMotorClient:
return client
#application.post("/createStudent")
async def create_student(student = Body(...), db: AsyncIOMotorClient = Depends(get_database)):
new_student = await db["college"]["students"].insert_one(student)
created_student = await db["college"]["students"].find_one({"_id": new_student.inserted_id})
return JSONResponse(status_code=status.HTTP_201_CREATED, content=created_student)
#application.post("/createTeacher")
async def create_teacher(teacher = Body(...), db: AsyncIOMotorClient = Depends(get_database)):
new_teacher = await db["college"]["students"].insert_one(teacher)
created_teacher = await db["college"]["students"].find_one({"_id": new_teacher.inserted_id})
return JSONResponse(status_code=status.HTTP_201_CREATED, content=created_teacher)
handler = Mangum(application)
For every API request, new connection is created. How to cache db so that new request uses old connection. Every time new request is created so that lambda compute time is increased dramatically after db hits max connection limit.
There are examples for node js but for python I could not find anywhere

schema_translate_map for SQLALchemy AsyncSession

I need to change PostgreSQL schema in SQLAlchemy AsyncSession session.
For sync Session we have session.connection(execution_options={"schema_translate_map": {None: schema}})
For async I found a way to do it: MyModel.__table__.schema = "MySchema, but it will change the model in runtime which is really bad for async code.
Is there something like schema_translate_map for AsyncSession?
I had the same exact problem and the way I fix it is doing like this:
from asyncio import current_task
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_scoped_session
from sqlalchemy.orm import sessionmaker
async def main()
db_connstring = "postgresql+asyncpg://scott:tiger#localhost/test"
engine = create_async_engine(db_connstring, pool_pre_ping=True)
session = async_scoped_session(
sessionmaker(bind=engine, expire_on_commit=False, class_=AsyncSession),
scopefunc=current_task)
schema = "my_schema"
connection = await session.connection()
await connection.execution_options(schema_translate_map={None: schema})
...

AttributeError: 'str' object has no attribute 'client'

I have a code where, I am establishing connection with MongoDB. This code is
ConnectMongoDB.py:
import pymongo
from pymongo import MongoClient
from flask import Flask, render_template, request,redirect,url_for
app = Flask(__name__)
# Connection to MongoDB
class ConnectMdb:
#staticmethod
def connect2mongodb():
global client
try:
client = pymongo.MongoClient("mongodb") # modified to avoid showing actual string. Kindly ignore this part.
print("Connected to Avengers MongoClient Successfully!!!")
print (type(client))
print(client)
except:
print("Connection to MongoClient Failed!!!")
#db = client.avengers_hack_db
return("Connection established")
if __name__ == '__main__':
ConnectMdb.connect2mongodb()
I import this script in another program which has some business logic. Here is some part of the code which is relevant to this issue:
ProcessData.py:
import pymongo
from pymongo import MongoClient
import datetime
import sys
from flask import Flask, render_template, request
#import ProcessTaskData
#import werkzeug
import ConnectMongoDB as cDB
app = Flask(__name__)
CMdb = cDB.ConnectMdb.connect2mongodb()
db = CMdb.client.avengers_hack_db
#app.route('/')
def index():
return render_template('index.html')
#app.route('/Avengers',methods = ['POST'])
def Avengers():
ip = request.remote_addr
Project_ID = request.form['pid']
Name = request.form['pname']
Resource_Names = request.form['rsrc']
db.ppm_master_db_collection.insert_many([
{"Org_Id":"",
"Name": Name,
"last_modified": datetime.datetime.utcnow()}
])
return render_template('ptasks.html', user_ip=ip)
#app.route('/ProjectTasks',methods = ['POST'])
def ProjectTask():
ip = request.remote_addr
Task_ID = request.form['tid']
TAlert = request.form['talrt']
TResource_Names = request.form['trsrc']
db.ppm_tasks_data_collection.insert_many([
{"Task_ID": Task_ID,
"Resource_Names": TResource_Names,
"last_modified": datetime.datetime.utcnow()}
])
return render_template('ptasks.html', user_ip=ip)
if __name__ == '__main__':
app.run(debug = True)
If I put the code from ConnectMongoDB.py directly in the ProcessData.py rather than importing, it works good. But from separate file it errors.
Also, client is of type:
<class 'pymongo.mongo_client.MongoClient'>
Ideally it is expected to behave normally (establish connection to db as well) like when the code is in the ProcessData.py. Not sure where am I missing.
Changing
db = CMdb.client.avengers_hack_db
to
db = cDB.client.avengers_hack_db
should make your error go away, you are referencing the wrong thing. The return value of your staticmethod is a string, and it has no client attribute.
A bit better approach would be if your connect2mongodb method would return client:
class ConnectMdb:
#staticmethod
def connect2mongodb():
try:
client = pymongo.MongoClient("mongodb") # modified to avoid showing actual string. Kindly ignore this part.
print("Connected to Avengers MongoClient Successfully!!!")
print (type(client))
print(client)
except:
raise Exception("Connection to MongoClient Failed!!!")
return client
This way db = CMdb.client.avengers_hack_db would work.

Categories

Resources