I'm trying to re-start work for a previous project and Database server was deleted.
No database backup or SQL script. But schema is defined in Python Database Model.
Can I generate Database schema from it?
I have the following class defined:
class News(db.Model, AutoSerialize, Serializer):
__tablename__ = 'news'
news_id = Column(Integer, primary_key=True, server_default=text(
"nextval('news_news_id_seq'::regclass)"))
source = Column(String(64))
source_id = Column(String(64))
author = Column(String(128))
title = Column(String(256), nullable=False)
description = Column(String(65536))
url = Column(String(512))
url_to_image = Column(String(512))
published_at = Column(Date())
content = Column(String(65536))
campaign = Column(String(16))
score = Column(Float(53))
magnitude = Column(Float(53))
sentiment = Column(String(16))
rank_score = Column(Float(53))
rank_order = Column(Integer)
translated_content = Column(String(65536))
detected_language = Column(String(128))
inserted_at = Column(DateTime(True))
and
t_tags = Table(
'tags', metadata,
Column('tag_id', Integer, nullable=False,
server_default=text("nextval('tags_tag_id_seq'::regclass)")),
Column('tag_name', String(128), nullable=False)
)
When you have got the metadata and connection, you can just do
metadata.create_all(connection)
(I assume db.Model is a declarative base)
Related
I have a one to many relationship between a Project and a Note (i.e. a project will have many notes but a note belongs to a single project) in my Flask app:
class BaseDocument(db.Model):
__abstract__ = True
created_at = db.Column(db.DateTime, default=datetime.now)
updated_at = db.Column(db.DateTime, onupdate=datetime.now)
archived = db.Column(db.Boolean, default=False)
def __repr__(self):
return str(self.__dict__)
class Project(BaseDocument):
__tablename__ = "project"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
parent_id = db.Column(db.Integer, db.ForeignKey("project.id"))
notes = db.relationship(
"Note",
backref="project",
lazy=True,
order_by="Note.updated_at",
cascade="all, delete, delete-orphan",
)
class Note(BaseDocument):
__tablename__ = "note"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
content = db.relationship(
"Bullet", backref="note", lazy=True, order_by="Bullet.order"
)
project_id = db.Column(db.Integer, db.ForeignKey("project.id"))
I would like to do something that seems to be very simple but I can't figure out how: I want to update the archived property of all the child notes in a project to True if the parent project archived property is also set to True.
I can only find answers here in StackOverfow about how to update the parent object if a child is updated (the oposite of what I am trying to do), so I am assuming that what I want to do is trivial and I am just bad at sqlalchemy. How can I set this up? Do I need to use a after_update event on Project? If yes, how can I access all the child Notes and set archived=True for all of them?
I have tried to setup the following event listener with no success, I get the following error AttributeError: 'InstrumentedList' object has no attribute 'update':
#db.event.listens_for(Project, "after_update")
def archive_notes(mapper, connection, target):
obj = target.object
connection.execute(target.notes.update(archived=True))
Any help will be very appreciated!
You're on the right track by using after_update. Here's a working example:
import sqlalchemy as sa
from sqlalchemy.orm import declarative_base, relationship
connection_uri = (
"mssql+pyodbc://#localhost:49242/myDb?driver=ODBC+Driver+17+for+SQL+Server"
)
engine = sa.create_engine(
connection_uri,
future=True,
echo=False,
)
Base = declarative_base()
class Project(Base):
__tablename__ = "project"
id = sa.Column(sa.Integer, primary_key=True)
title = sa.Column(sa.Unicode(100), nullable=False)
archived = sa.Column(sa.Boolean, nullable=False, default=False)
class ProjectNote(Base):
__tablename__ = "project_note"
id = sa.Column(sa.Integer, primary_key=True)
project_id = sa.Column(sa.Integer, sa.ForeignKey("project.id"))
project = relationship(Project)
note_text = sa.Column(sa.Unicode(255), nullable=False)
archived = sa.Column(sa.Boolean, nullable=False, default=False)
#sa.event.listens_for(Project, "after_update")
def archive_remaining_project_notes(mapper, connection, target):
if target.archived:
sql = """\
UPDATE project_note SET archived = :yes
WHERE project_id = :proj_id
AND archived = :no
"""
connection.execute(
sa.text(sql),
{"yes": True, "no": False, "proj_id": target.id},
)
# <just for testing>
Base.metadata.drop_all(engine, checkfirst=True)
Base.metadata.create_all(engine)
# </just for testing>
p1 = Project(title="project 1")
p1n1 = ProjectNote(
project=p1, note_text="project 1, note 1, archived", archived=True
)
p1n2 = ProjectNote(project=p1, note_text="project 1, note 2, not archived")
with sa.orm.Session(engine, future=True) as session:
session.add_all([p1, p1n1, p1n2])
session.commit()
print(f"p1n2.archived is: {p1n2.archived}") # p1n2.archived is: False
p1.archived = True
session.commit()
print(f"p1.archived is: {p1.archived}") # p1.archived is: True
print(f"p1n2.archived is: {p1n2.archived}") # p1n2.archived is: True
In the following code snippet, In the events table event_id is created first and then i need to insert multiple records into even_logins table based on the event_id.
class Events(db.Model):
__tablename__ = 'events'
event_name= db.column(db.String(100))
event_id = db.Column(db.String(10),primary_key=True)
scheduled_date = db.Column(db.DateTime, nullable = False)
event_logins_event_id = db.Column(db.String(10), db.ForeignKey('event_logins.event_id'))
event_registrations_event_id = db.Column(db.String(10), db.ForeignKey('event_registrations.event_id'))
class Event_logins(db.Model):
__tablename__ = 'event_logins'
event_id= db.column(db.String(10),db.ForeignKey('events.event_id'))
username = db.Column(db.String(20),primary_key=True)
password = db.Column(db.String(300))
class Event_registrations(db.Model):
__tablename__ = 'event_registrations'
event_id= db.column(db.String(10), db.ForeignKey('events.event_id'))
registration_id = db.Column(db.String(50),primary_key=True)
cust_name = db.Column(db.String(100))
cust_contactno = db.Column(db.String(50))
cust_email = db.Column(db.String(50))
cust_imageid = db.Column(db.String(200))
Finally with the below query am trying insert a record into event_logins table
event_logins = Event_logins(event_id='jk12',username='testuser', password='aaaa')
db.session.add(event_logins)
db.session.commit()
In the table it is stored as NULL the value is not being stored pls suggest
Thanks
vijay
I am using sqlachemy with MySQL backend. Actually having problems optimizing a query.
I have the following set of models:
class Book(Base):
__tablename__ = 'books'
name = Column(String(32), primary_key=True)
sku = Column(Integer, nullable=False)
class Author(Base):
__tablename__ = 'authors'
name = Column(String(64), primary_key=True)
# book
books = relationship(Book, secondary=Table(
'author_books', Base.metadata,
Column('author', String(32),
ForeignKey(Author.name), primary_key=True),
Column('book', String(64), ForeignKey("book.title"),
primary_key=True)
), backref=backref('book_authors', cascade="save-update"))
And was doing a query:
authors_with_books = [(autor.name, [book.name for book in books]) for author in session.query(Authors)]
Which is actually very very slow :(
Your query is slow because you are joining data on python.
Do it on database.
try something like that:
authors_with_books = session.query(Author.name, Book.name)
It'll create a join on SQL
authors_with_books = session.query(Author).join(Author.books)
or
Use 'lazyload' param.
Try rewrite many_to_many table in models. It's work for me:
class Author(Base):
__tablename__ = 'authors'
name = Column(String(64), primary_key=True)
books = relationship('Book', secondary='author_books')
author_book = Table(
'author_books', Base.metadata,
Column('author', String(32), ForeignKey("author.name", match=u'FULL'), primary_key=True),
Column('book', String(64), ForeignKey("book.title", match=u'FULL'), primary_key=True)
)
And I think ForeignKey(Author.name) - Incorrect code, fix it.
I created a Table a Bmarks which has two foreign keys which have relation with same table Url_hash
class Hashed(Base):
__tablename__ = "url_hash"
hash_id = Column(Unicode(22), primary_key=True)
url = Column(UnicodeText)
clicks = Column(Integer, default=0)
def __init__(self, url):
cleaned_url = str(unidecode(url))
self.hash_id = unicode(generate_hash(cleaned_url))
self.url = url
class Bmark(Base):
__tablename__ = "bmarks"
bid = Column(Integer, autoincrement=True, primary_key=True)
hash_id = Column(Unicode(22), ForeignKey('url_hash.hash_id'))
clean_hash_id = Column(Unicode(22), ForeignKey('url_hash.hash_id'))
description = Column(UnicodeText())
extended = Column(UnicodeText())
stored = Column(DateTime, default=datetime.utcnow)
updated = Column(DateTime, onupdate=datetime.utcnow)
clicks = Column(Integer, default=0)
inserted_by = Column(Unicode(255))
username = Column(Unicode(255), ForeignKey('users.username'),
nullable=False,)
tag_str = Column(UnicodeText())
hashed = relation(Hashed,
foreign_keys="Bmark.hash_id",
backref="bmark",
uselist=False
)
clean_hashed = relation(Hashed,
foreign_keys="Bmark.clean_hash_id",
backref="bmark",
uselist=False
)
I am trying to store url after cleaning it a little bit like removing headers,utm parameters etc for indexing purposes
Error is occurring while creating the database
sqlalchemy.exc.ArgumentError: Error creating backref 'bmark' on relationship 'Bmark.clean_hashed': property of that name exists on mapper 'Mapper|Hashed|url_hash'
Actually the error message is very informative.
Just rename one of your backref="bmark" to something else like backref="my_clean_bmark".
So I recently changed from sqlite to postgres so that I could push my site to heroku. The issue I am having is that the tables are now getting built out of order??
class Data(Base):
__tablename__ = 'data'
id = Column(Integer, autoincrement=True, primary_key=True)
data_type = Column(Integer, primary_key=True, unique=True)
value = Column(Text, primary_key=True, unique=True)
range_lower = Column(Integer)
range_upper = Column(Integer)
gold = Column(Boolean)
def __init__(self, data_type, value, range_lower=0, range_upper=0, gold=False):
self.data_type = data_type
self.value = value
self.range_lower = range_lower
self.range_upper = range_upper
self.gold = gold
class Page(Base):
__tablename__ = 'page'
id = Column(Integer, autoincrement=True, primary_key=True)
data_type = Column(Integer, ForeignKey('data.data_type'))
description = Column(Text)
annotations_per_page = Column(Integer)
uses_gold = Column(Boolean)
def __init__(self, data_type, description='default description', annotations_per_page=1, uses_gold=False):
self.data_type = data_type
self.description = description
self.annotations_per_page = annotations_per_page
self.uses_gold = uses_gold
The issue I am having is that sqlalchemy/pyramid or whatever the populate script generated by python setup.py develop on one of these types of projects, is trying to create the table Page before the table Data. Since there are foreign keys in Page that depend on Table, this is failing. I can't find any mention of this issue in the documentation, any insight would be greatly appreciated.
-Sam
you need to use database metadata
and these functions
metadata =MetaData()
creat_all()
it generates the tables in order of their dependency.
ref:http://docs.sqlalchemy.org/en/rel_0_7/core/schema.html