I am trying to use SQLAlchemy automap to map an existing MSSQL view. I can successfully automap a table and perform queries against it but as soon as I target a view it fails. Here is some code of a couple of different attempts I have tried.
Mapping a standard table works with the following:
engine = create_engine("mssql+pyodbc://username:password#serv.example.com/db?driver=ODBC+Driver+13+for+SQL+Server")
metadata = MetaData()
metadata.reflect(engine, only=['table_name'])
Base = automap_base(metadata=metadata)
Base.prepare()
table = Base.classes.table_name
Mapping a view with the following fails
engine = create_engine("mssql+pyodbc://username:password#serv.example.com/db?driver=ODBC+Driver+13+for+SQL+Server")
metadata = MetaData()
metadata.reflect(engine, only=['view_name'], views=True)
Base = automap_base(metadata=metadata)
Base.prepare()
view = Base.classes.view_name
EDIT: I have now tried to create a class which maps a unique column as the primary key but I am still getting errors. Here is what I am trying.
Base.automap()
class view_name(Base):
__tablename__ = 'view_name'
some_id = Column('some_id', Integer, primary_key=True)
engine = create_engine("mssql+pyodbc://username:password#serv.example.com/db?driver=ODBC+Driver+13+for+SQL+Server")
metadata = MetaData()
metadata.reflect(engine, only=['view_name'], views=True)
Base.prepare()
view = Base.classes.view_name
And I am now getting the following error.
AttributeError: view_name
Here's what worked for me.
from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine, MetaData, Column, Integer, Table
from sqlalchemy.orm import Session
Base = automap_base()
conn_str = '...'
engine = create_engine(conn_str)
metadata = MetaData()
# you only need to define which column is the primary key. It can automap the rest of
the columns.
viewname = Table('view_name',metadata, Column('some_id', Integer,
primary_key=true), autoload=True, autoload_with=engine)
Base.prepare()
view_name = Base.classes.view_name
session = Session(engine)
v1 = session.query(view_name).first()
For anyone who still can get it working try this:
Table('view_name',Base.metadata, Column('some_id', Integer,
primary_key=True), autoload=True, autoload_with=engine)
Base.prepare(engine, reflect=True)
Related
I want to create an api for login authentication. I have used the below method to create the table, but I don't want to create a new table but instead use an existing table.
main.py
from fastapi import FastAPI
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from database import Base, engine, SessionLocal
class User( Base ):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
is_active = Column(Boolean, default=True)
items = relationship("Item", back_populates="owner")
Base.metadata.create_all(bind=engine)
database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
SQLALCHEMY_DB_URL = "mysql://root:mumbaicity#localhost:3306/ryr"
engine = create_engine(SQLALCHEMY_DB_URL)
SessionLocal = sessionmaker(autocommit=False, bind=engine)
Base = declarative_base()
conn = engine.connect()
this is the table I want to use: (employee):
enter image description here
You can simply not run Base.metadata.create_all(bind=engine) and define a class for the table you want.
If you have many tables and want to automatically generate model classes, look into sqlacodegen.
I has a FastAPI project where I have main.py, endpoints.py (with endpoint functions) and users_db.py where I have list of dictionaries. Every dictionary save users data. It just pet project to understand web application. An now I want to create database. I chose SQL. Can somebody explaine or give a link where is described how to do that?! Or is it very hard?!
it's very simple.
first you need install sqlalchemy
pip install SQLAlchemy
then create database.py file and paste the following code to that.
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
then create models.py file and write some database models you need.
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from .database import Base
class User(Base):
__tablename__ = "users" # this is table name
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True, index=True)
hashed_password = Column(String)
is_active = Column(Boolean, default=True)
Read the documentation for more information.
documentation
I created declarative table.
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String
from sqlalchemy.dialects.postgresql import UUID
import uuid
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True)
name = Column(String)
I need to filter data. In the Flask-SQLAlchemy, I do
name = 'foo'
User.query.filter_by(name=name).first()
But if I use SQLAlchemy without Flask, then I get the error:
type object 'User' has no attribute 'query'
The only way that works for me is to filter the data through the session.
engine = create_engine('DATABASE_URL')
Session = sessionmaker(bind=engine)
session = Session()
name = 'foo'
user = session.query(User).filter_by(name=name).first()
session.close()
The Model.query... idiom is not a default part of the SQLAlchemy ORM; it's a customisation provided by Flask-SQLAlchemy. It is not available in base SQLAlchemy, and that is why you get the error message.
Why? ...because query object is not set on Base/model object automatically.
Solution is to add this line to your base:
Base.query = SessionLocal.query_property()
(where SessionLocal is instance of scoped_session)
This will make query available on all of your models and should solve your issue.However, mypy and pylint will still be complaining about this (that's how I found this question).
I have a test database with two entities: post and category and I'm using declarative base to perform the manipulation of the data in my base, as follows:
engine = create_engine("sqlite:///test.db")
Base = declarative_base()
Base.metadata.bind = engine
class Post(Base):
__tablename__ = "post"
post_id = Column('id', primary_key=True)
title = Column('title')
...other attributes...
class Category(Base):
__tablename__ = "category"
category_id = Column('id', primary_key=True)
description = Column('name')
...other attributes...
Assuming I wanted to create a relationship between post and category (which does not exist in my database), how do I create it? Any idea?
Edit1:
I'll try to be clearer: the database already exists where a bind is done, as well as the post and category tables. What I want is to create a relationship between them through the code and write this in the database
create_all method support specify tables to create:
Base.metadata.create_all(tables=[Post.__table__,])
result:
$ sqlite3 test.db
sqlite> .tables
post
I am creating a table in my Oracle DB using python and sqlalchemy. I would like to have an auto-increment ID column as primary key. How can I modify the following code to add the autoload option or anything like that ?
engine = creat_engine("oracle:// ....")
Base = declarative_base()
class MyTable(Base):
__tablename__ = 'MyTable'
ID = Column(Integer, Sequence('my_id_seq'), primary_key=True)
SomeColumn = Column(VARCHAR(50))
Base.metadata.create_all(engine)
p.s. I don't want to create a separate sequence and trigger (as shown here).
UPDATE:
when trying to do the following, I get syntax error because of "autoload=True":
class MyTable(Base):
__table__ = Table('myTable', Base.metadata, autoload=True,
Column('id', Integer, Sequence('my_id_seq'), primary_key=True),
Column('somecolumn', VARCHAR(50))
)
SyntaxError: non-keyword arg after keyword arg