I am new to the FastAPI world, I am creating an API to fetch and post the data to the MySQL database. I followed few link on internet and developed below code
DatabaseConnection.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
sql_database_url="mysql://root:root#localhost:3306/first_db"
engine=create_engine(sql_database_url)
sessionLocal=sessionmaker(autocommit=False,bind=engine)
base=declarative_base()
MainClass.py
from fastapi import FastAPI,Query,Depends
from sqlalchemy import Column,String,Integer
from typing import Optional,List
from pydantic import BaseModel
from sqlalchemy.orm import Session
from DatabaseConnection import engine,sessionLocal,base
app=FastAPI()
class User(base):
__tablename__="users"
id=Column(Integer,primary_key=True,index=True)
name=Column(String(255),unique=True,index=True)
class UserSchema(BaseModel):
id:int
name:str
class Config:
orm_model=True
base.metadata.create_all(bind=engine)
#app.post("/create-user")
def createUser(userSchema:UserSchema):
user=User(id=userSchema.id,name=userSchema.name)
sessionLocal().add(user)
sessionLocal().commit()
return user
When i try to run this API using UVICorn i was running successful and the table also created successfully but the data that i am sending through the body is not added in the table.
The table is showing null value is added \
I have referred link
Any help will be appreciated. Thanks in advance
Thanks #anjaneyulubatta505 for help
but we need to do below changes to post data in database
#app.post("/create-user")
def createUser(userSchema:UserSchema):
user = User(id=userSchema.id, name=userSchema.name)
with Session(bind=engine) as session:
session.add(user)
session.commit()
return user
referred links
Link1
Link2 from sqlAlChemy
You are not committing the change to the database. Just change your code like below to make it work.
# ... imports and other stuff
from DatabaseConnection import sessionLocal
#app.post("/create-user")
def createUser(userSchema:UserSchema):
user = User(id=userSchema.id, name=userSchema.name)
with sessionLocal() as session:
session.add(user)
session.commit()
return user
Related
I am having trouble writing tables to a postgres database using SQLAlchemy ORM and Python scripts.
I know the problem has something to do with incorrect Session imports because when I place all the code below into a single file, the script creates the table without trouble.
However, when I break the script up into multiple files (necessary for this project), I receive the error "psycopg2.errors.UndefinedTable: relation "user" does not exist".
I have read many posts here on SO, tried reorganising my files, the function call order, changing from non-scoped to scoped sessions, eliminating and adding Base.metadata.create_all(bind=engine) in various spots, changed how the sessions are organised and created in base.py, as well as other things, but the script still errors and I'm not sure which code sequence is out of order.
The code currently looks like:
base.py:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
# SQLAlchemy requires creating an Engine to interact with our database.
engine = create_engine('postgresql://user:pass#localhost:5432/testdb', echo=True)
# Create a configured ORM 'Session' factory to get a new Session bound to this engine
#_SessionFactory = sessionmaker(bind=engine)
# Use scoped session
db_session = scoped_session(
sessionmaker(
bind=engine,
autocommit=False,
autoflush=False
)
)
# Create a Base class for our classes definitions
Base = declarative_base()
models.py
from sqlalchemy import Column, DateTime, Integer, Text
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
email = Column(Text, nullable=False, unique=True)
name = Column(Text)
date_last_seen = Column(DateTime(timezone=True))
def __init__(self, email, name, date_last_seen):
self.email = email
self.name = name
self.date_last_seen = date_last_seen
inserts.py
from datetime import date
from base import db_session, engine, Base
from models import User
def init_db():
# Generate database schema based on our definitions in model.py
Base.metadata.create_all(bind=engine)
# Extract a new session from the session factory
#session = _SessionFactory()
# Create instance of the User class
alice = User('alice#throughthelooking.glass', 'Alice', date(1865, 11, 26))
# Use the current session to persist data
db_session.add(alice)
# Commit current session to database and close session
db_session.commit()
db_session.close()
print('Initialized the db')
return
if __name__ == '__main__':
init_db()
Thank you for any insight you're able to offer!
I have a web application that is on top of mysql. When I started it, I built the mysql database from scratch, and connected to it using pymysql.
Fast forward...
I've rewritten everything using sqlalchemy to connect to the db (non-declarative?) I can connect to the db, read the db, update, etc. I also use MySQLWorkbench to view the database in a graphic way.
My webapp has a few tables that will poll the database for changes, and update the table. For instance, I have a job queue which will update the percentage-done. Here's the kicker:
When I send a job through, I will watch the database in MySQLWorkbench. I can verify that the job is going through (I see the percentage climbing). This confirms that the webapp is writing to the database. But! On the other end, where the table is asking for the status, it is not recieving the updated information (I've done print outs in the models, as well as in the flask app, as well as the FE js).
What is going on here? Even though I can see it in MySQLWorkbench is the connection not 'releasing' or something? Here is some of my code:
#models.py
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker, Query
import os
import json
Base = automap_base()
engine = create_engine("mysql+pymysql://user:asdas758ef10d2364d54d7e8#localhost:{}/metadatacontroller".format(3306))
# reflect the tables
Base.prepare(engine, reflect=True)
EncodeQueue = Base.classes.encode_queue
db_session = scoped_session(sessionmaker(bind=engine))
class DataStore:
def __init__(self):
self.db = db_session()
#receive status
def queue_rendering_items(self):
query = self.db.query(EncodeQueue).filter(EncodeQueue.status.in_(['queue', 'rendering', 'rendering thumbnails'])).all()
return_query = []
for item in query:
row = {'artist_id': item.artist_id,
'art_id': item.art_id,
'status': item.status,
'progress': item.errors,
'artwork_title': item.artwork_title,
'artist_name': item.artist_name,
}
return_query.append(row)
return return_query
#update status
def update_render_progress(self, job_id, progress):
self.db.query(EncodeQueue).filter_by(job_id=job_id).update\({'errors': json.dumps(progress)})
self.db.commit()
(ignore the back slash in update_render_progress ... weird SO formatting)
This is how 'status' code is being called on a flask end point:
#app.route('/api/jobs', methods=["GET"])
def get_all_jobs():
db = models.DataStore()
all_art = db.queue_rendering_items()
print(all_art)
return jsonify({'data':all_art})
Lastly, the status is being updated by a different file, on a different machine:
import models
db = models.DataStore()
db.update_render_progress(job_id, {'percentage': percentage_complete, 'time_remain': render.render_estimated_seconds_remaining})
What the heck is happening?
I am using SQLAlchemy in my python command line app. The app is basically reading a set of URLs and doing inserts into a postgreql database based on the data.
After about the same number of inserts (give or take a few), the entire app freezes.
Having seen python sqlalchemy + postgresql program freezes I am assuming I am doing something wrong with the SQLAlchemy Session (although I am not using drop_all(), which seemed to be the cause of that issue). I've tried a couple of things but thus far they have had no impact.
Any hints or help would be welcome. If my integration of SQLAlchemy into my app is incorrect, a pointer to a good example of doing it right would also be welcome.
My code is as follows:
Set up the sql alchemy base:
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
Create the session info and attach it to the Base
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
engine = create_engine("sqlite:///myapp.db")
db_session = scoped_session(sessionmaker(bind=engine))
Base.query = db_session.query_property()
Base.scoped_db_session = db_session
Create my model from Base and make use of the session
class Person(Base):
def store(self):
if self.is_new():
self.scoped_db_session.add(self)
self.scoped_db_session.commit()
If I create enough objects of type Person and call store(), the app eventually freezes.
Managed to solve the problem. Turns out that my implementation is specifically on the don't do it this way list (see http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#session-frequently-asked-questions E.g. don't do this) and I was not managing the session correctly
To solve my problem I moved the session out of the model into a separate class, so instead of having calls like:
mymodel.store()
I now have:
db.current_session.store(mymodel)
where db is an instance of my custom DBContext below:
from contextlib import contextmanager
from sqlalchemy.orm import scoped_session, sessionmaker
class DbContext(object):
def __init__(self, engine, session=None):
self._engine = engine
self._session = session or scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=self._engine))
self.query = self._session.query_property()
self.current_session = None
def start_session(self):
self.current_session = self._session()
def end_session(self):
if self.current_session:
self.current_session.commit()
self.current_session.close()
self.current_session = None
#contextmanager
def new_session(self):
try:
self.start_session()
yield
finally:
self.end_session()
When you want to store one or more model objects, call DBContext.start_session() to start a clean session. When you finally want to commit, call DBContext.end_session().
I started with sqlalchey and everything is good. But my question is: How to use session on a correct way.
For example:
I have a file like (sqlsetts.py):
from sqlalchemy import create_engine
engine = create_engine('mysql://root#127.0.0.1/test')
engine.execute("SET NAMES 'utf8'")
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine, autoflush=True, autocommit=True, expire_on_commit=True)
session = Session()
Every time I need to use a session i use following:
class test:
from sqlsettings import session
def testfunc(self):
self.session.query... bla bla
Is that correct way to include session from a file or to make a new one for each function?
I am just starting with SQLAlchemy and I have been wondering... I am going to have a lot of tables in my model. I would like to have own file for each table I will have in my model.
I am currently using following code:
from sqlalchemy import MetaData
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects import postgresql
import sqlalchemy as sa
__all__ = ['Session', 'engine', 'metadata']
# SQLAlchemy database engine. Updated by model.init_model()
engine = None
# SQLAlchemy session manager. Updated by model.init_model()
Session = scoped_session(sessionmaker())
# Global metadata. If you have multiple databases with overlapping table
# names, you'll need a metadata for each database
metadata = MetaData()
# declarative table definitions
Base = declarative_base()
Base.metadata = metadata
schema = 'srbam_dev'
in meta.py
Following in _init_.py
"""The application's model objects"""
import sqlalchemy as sa
from sqlalchemy import orm
from models import meta
from models.filers import Filer
from models.vfilers import Vfiler
from models.filer_options import FilerOption
def init_models(engine):
"""Call me before using any of the tables or classes in the model"""
## Reflected tables must be defined and mapped here
#global reflected_table
#reflected_table = sa.Table("Reflected", meta.metadata, autoload=True,
# autoload_with=engine)
#orm.mapper(Reflected, reflected_table)
#
meta.engine = sa.create_engine(engine)
meta.Session.configure(bind=meta.engine)
class Basic_Table(object):
id = sa.Column(
postgresql.UUID(),
nullable=False,
primary_key=True
)
created = sa.Column(
sa.types.DateTime(True),
nullable=False
)
modified = sa.Column(
sa.types.DateTime(True),
nullable=False
)
And then following in all of my models
from models.meta import Base
from models.meta import Basic_Table
from models.meta import schema
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
class Filer(Base,Basic_Table):
This works just fine, as long as I do not start to use some Foreign Keys on tables, once I use Foreign Key says
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 't_vfilers.filer_id' could not find table 't_filers' with which to generate a foreign key to target column 'id'
I tried to define id key directly in Filer class (and remove Basic_Table from declaration), however this does not solve the issue.
My code for creating the database looks like this
#!/usr/bin/python
import ConfigParser
from sqlalchemy.engine.url import URL
from models import *
config = ConfigParser.RawConfigParser()
config.read('conf/core.conf')
db_url = URL(
'postgresql+psycopg2',
config.get('database','username'),
config.get('database','password'),
config.get('database','host'),
config.get('database','port'),
config.get('database','dbname')
)
init_models(db_url)
meta.Base.metadata.drop_all(bind=meta.engine)
meta.Base.metadata.create_all(bind=meta.engine)
Does anyone have an idea how to fix this issue?
Marek,do one thing try defining the foreign key along with the schema name i.e 'test.t_vfilers.filer_id'(here 'test' is the schema name),this will solve the problem.
Have you remembered to import the different modules containing the models.
In my init.py I have at the bottom a ton of:
from comparty3.model.users import User, UserGroup, Permission
from comparty3.model.pages import PageGroup, Page
etc...
If that's not the issue then I'm not sure; however have you tried to change:
metadata = MetaData()
# declarative table definitions
Base = declarative_base()
Base.metadata = metadata
to:
# declarative table definitions
Base = declarative_base()
metadata = Base.metadata
I'm guessing here, but it may be that declarative_base() creates a special metadata object.
This is how it is defined in my pylons projects (were I'm guessing your code is from too).