Data Management With Python, SQLite, and SQLAlchemy
Data Management With Python, SQLite, and SQLAlchemy
realpython.com
61-78 minutes
You can achieve similar results using flat files in any number of
formats, including CSV, JSON, XML, and even custom formats.
Flat files are often human-readable text files—though they can
also be binary data—with a structure that can be parsed by a
computer program. Below, you’ll explore using SQL databases
and flat files for data storage and manipulation and learn how to
decide which approach is right for your program.
You can get all of the code and data you’ll see in this tutorial by
clicking on the link below:
1 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
first_name,last_name,title,publisher
Isaac,Asimov,Foundation,Random House
Pearl,Buck,The Good Earth,Random House
Pearl,Buck,The Good Earth,Simon & Schuster
Tom,Clancy,The Hunt For Red October,Berkley
Tom,Clancy,Patriot Games,Simon & Schuster
2 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Stephen,King,It,Random House
Stephen,King,It,Penguin Random House
Stephen,King,Dead Zone,Random House
Stephen,King,The Shining,Penguin Random House
John,Le Carre,"Tinker, Tailor, Soldier, Spy: A
George Smiley Novel",Berkley
Alex,Michaelides,The Silent Patient,Simon &
Schuster
Carol,Shaben,Into The Abyss,Simon & Schuster
3 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
4 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
The authors Stephen King and Tom Clancy appear more than
once because multiple books they’ve published are represented
in the data.
The authors Stephen King and Pearl Buck have the same book
published by more than one publisher.
Lastly, it adds a new book to the data and redisplays the tree
hierarchy with the new book in place. Here’s the main() entry-
point function for this program:
1def main():
5 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
6 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
25 data = add_new_book(
26 data,
27 author_name="Stephen King",
28 book_title="The Stand",
29 publisher_name="Random House",
30 )
31
32 # Output the updated hierarchical authors
data
33 output_author_hierarchy(data)
$ python main.py
Publisher: Simon & Schuster, total books: 4
Publisher: Random House, total books: 4
Publisher: Penguin Random House, total books: 2
Publisher: Berkley, total books: 2
7 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Authors
├── Alex Michaelides
│ └── The Silent Patient
│ └── Simon & Schuster
├── Carol Shaben
│ └── Into The Abyss
│ └── Simon & Schuster
├── Isaac Asimov
│ └── Foundation
│ └── Random House
├── John Le Carre
│ └── Tinker, Tailor, Soldier, Spy: A George
Smiley Novel
│ └── Berkley
├── Pearl Buck
│ └── The Good Earth
│ ├── Random House
│ └── Simon & Schuster
├── Stephen King
│ ├── Dead Zone
│ │ └── Random House
│ ├── It
│ │ ├── Penguin Random House
│ │ └── Random House
│ └── The Shining
│ └── Penguin Random House
└── Tom Clancy
├── Patriot Games
8 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
main() calls other functions to perform the bulk of the work. The
first function it calls is get_data():
def get_data(filepath):
"""Get book data from the csv file"""
return pd.read_csv(filepath)
This function takes in the file path to the CSV file and uses
pandas to read it into a pandas DataFrame, which it then
passes back to the caller. The return value of this function
becomes the data structure passed to the other functions that
make up the program.
9 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
data.assign(name=data.first_name.str.cat(data.last_name
sep=" "))
.groupby("publisher")
.nunique()
.loc[:, "name"]
.sort_values(ascending=ascending)
)
10 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
"first_name": first_name,
"last_name": last_name,
"title": book_title,
"publisher": publisher_name,
},
ignore_index=True,
)
def output_author_hierarchy(data):
"""Output the data as a hierarchy list of
authors"""
authors = data.assign(
name=data.first_name.str.cat(data.last_name, sep="
")
)
authors_tree = Tree()
authors_tree.create_node("Authors", "authors")
for author, books in authors.groupby("name"):
authors_tree.create_node(author, author,
parent="authors")
for book, publishers in
books.groupby("title")["publisher"]:
book_id = f"{author}:{book}"
authors_tree.create_node(book, book_id,
parent=author)
for publisher in publishers:
11 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
authors_tree.create_node(publisher,
parent=book_id)
Imagine if this data file contained more related data, like the
author’s address and phone number, publication dates and
ISBNs for books, or addresses, phone numbers, and perhaps
yearly revenue for publishers. This data would be duplicated for
each root data item, like author, book, or publisher.
12 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
numbers for home, work, mobile, and perhaps more? Every new
relationship that you’d want to add for any root item would
multiply the number of records by the number of items in that
new relationship.
13 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
14 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Here’s how you can create the three tables representing the
authors, books, and publishers in the CSV file using SQL
statements:
15 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
name VARCHAR
);
Once you’ve created and populated this table with author data
from the author_book_publisher.csv file, you can access it
using SQL statements. The following statement (also called a
query) uses the wildcard character (*) to get all the data in the
author table and output it:
You can use the sqlite3 command-line tool to interact with the
author_book_publisher.db database file in the
project/data directory:
$ sqlite3 author_book_publisher.db
sqlite> .q
16 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Notice that each author exists only once in the table. Unlike the
CSV file, which had multiple entries for some of the authors,
here, only one unique record per author is necessary.
This SQL statement inserts the values ‘Paul‘ and ‘Mendez‘ into
the respective columns first_name and last_name of the
author table.
UPDATE author
SET first_name = 'Richard', last_name = 'Bachman'
WHERE first_name = 'Stephen' AND last_name =
'King';
17 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
This SQL statement deletes a single row from the author table
where the first_name is equal to 'Paul' and the last_name is
equal to 'Mendez'.
Building Relationships
18 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
After getting all the data you want into one place in the CSV file,
why would you want to break it up into multiple tables? Wouldn’t
it be more work to create and put back together again? That’s
true to an extent, but the advantages of breaking up the data
and putting it back together using SQL could win you over!
One-to-Many Relationships
19 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
1. The small yellow and blue key icons indicate the primary and
foreign keys for the table, respectively.
20 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
When you add a new book to the book table, the data includes
an author_id value for an existing author in the author table.
In this way, all the books written by an author have a lookup
relationship back to that unique author.
Now that you have separate tables for authors and books, how
do you use the relationship between them? SQL supports
what’s called a JOIN operation, which you can use to tell the
database how to connect two or more tables.
The SQL query below joins the author and book table together
using the SQLite command-line application:
sqlite> SELECT
...> a.first_name || ' ' || a.last_name AS
author_name,
...> b.title AS book_title
...> FROM author a
...> JOIN book b ON b.author_id = a.author_id
...> ORDER BY a.last_name ASC;
Isaac Asimov|Foundation
Pearl Buck|The Good Earth
Tom Clancy|The Hunt For Red October
Tom Clancy|Patriot Games
Stephen King|It
Stephen King|Dead Zone
Stephen King|The Shining
John Le Carre|Tinker, Tailor, Soldier, Spy: A
George Smiley Novel
Alex Michaelides|The Silent Patient
Carol Shaben|Into The Abyss
21 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
The SQL query above gathers information from both the author
and book table by joining the tables using the relationship
established between the two. SQL string concatenation assigns
the author’s full name to the alias author_name. The data
gathered by the query are sorted in ascending order by the
last_name field.
Many-to-Many Relationships
22 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
1sqlite> SELECT
2 ...> a.first_name || ' ' || a.last_name AS
author_name,
23 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Line 2 selects the first and last name from the author table
using the a alias for the author table and concatenates them
together with a space character.
Line 4 uses the author table as the first source from which to
retrieve data and assigns it to the alias a.
24 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Note that the data in the source author and publisher tables
are normalized, with no data duplication. Yet the returned results
have duplicated data where necessary to answer the SQL
query.
1sqlite> SELECT
2 ...> a.first_name || ' ' || a.last_name AS
author_name,
3 ...> COUNT(b.title) AS total_books
4 ...> FROM author a
5 ...> JOIN book b ON b.author_id = a.author_id
6 ...> GROUP BY author_name
7 ...> ORDER BY total_books DESC, a.last_name
25 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
ASC;
8Stephen King|3
9Tom Clancy|2
10Isaac Asimov|1
11Pearl Buck|1
12John Le Carre|1
13Alex Michaelides|1
14Carol Shaben|1
The SQL query above returns the list of authors and the number
of books they’ve written. The list is sorted first by the number of
books in descending order, then by the author’s name in
alphabetical order:
Line 4 selects the author table to get data from and creates the
a alias.
26 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
27 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
The Model
28 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
29 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
13
14book_publisher = Table(
15 "book_publisher",
16 Base.metadata,
17 Column("book_id", Integer,
ForeignKey("book.book_id")),
18 Column("publisher_id", Integer,
ForeignKey("publisher.publisher_id")),
19)
20
21class Author(Base):
22 __tablename__ = "author"
23 author_id = Column(Integer, primary_key=True)
24 first_name = Column(String)
25 last_name = Column(String)
26 books = relationship("Book",
backref=backref("author"))
27 publishers = relationship(
28 "Publisher", secondary=author_publisher,
back_populates="authors"
29 )
30
31class Book(Base):
32 __tablename__ = "book"
33 book_id = Column(Integer, primary_key=True)
34 author_id = Column(Integer,
ForeignKey("author.author_id"))
35 title = Column(String)
36 publishers = relationship(
37 "Publisher", secondary=book_publisher,
back_populates="books"
38 )
30 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
39
40class Publisher(Base):
41 __tablename__ = "publisher"
42 publisher_id = Column(Integer,
primary_key=True)
43 name = Column(String)
44 authors = relationship(
45 "Author", secondary=author_publisher,
back_populates="publishers"
46 )
47 books = relationship(
48 "Book", secondary=book_publisher,
back_populates="publishers"
49 )
Line 5 creates the Base class, which is what all models inherit
from and how they get SQLAlchemy ORM functionality.
31 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
32 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Column("author_id", Integer,
ForeignKey("author.author_id"))
books = relationship("Book",
backref=backref("author"))
33 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
author_id = Column(Integer,
ForeignKey("author.author_id"))
publishers = relationship(
"Publisher", secondary=author_publisher,
back_populates="authors"
)
34 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
book = session.query(Book).filter_by(Book.title ==
"The Stand").one_or_none()
print(f"Authors name: {book.author.first_name}
{book.author.last_name}")
results = session.query(Author).all()
35 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
author_book_totals = (
session.query(
Author.first_name,
Author.last_name,
func.count(Book.title).label("book_total")
)
.join(Book)
.group_by(Author.last_name)
.order_by(desc("book_total"))
.all()
)
The query above gets the author’s first and last name, along
with a count of the number of books that the author has written.
The aggregating count used by the group_by clause is based
on the author’s last name. Finally, the results are sorted in
descending order based on the aggregated and aliased
book_total.
36 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Example Program
1def main():
2 """Main entry point of program"""
3 # Connect to the database using SQLAlchemy
4 with resources.path(
5 "project.data",
"author_book_publisher.db"
6 ) as sqlite_filepath:
7 engine =
create_engine(f"sqlite:///{sqlite_filepath}")
8 Session = sessionmaker()
9 Session.configure(bind=engine)
10 session = Session()
11
12 # Get the number of books printed by each
publisher
13 books_by_publisher =
get_books_by_publishers(session, ascending=False)
14 for row in books_by_publisher:
15 print(f"Publisher: {row.name}, total
books: {row.total_books}")
16 print()
17
18 # Get the number of authors each publisher
publishes
19 authors_by_publisher =
37 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
get_authors_by_publishers(session)
20 for row in authors_by_publisher:
21 print(f"Publisher: {row.name}, total
authors: {row.total_authors}")
22 print()
23
24 # Output hierarchical author data
25 authors = get_authors(session)
26 output_author_hierarchy(authors)
27
28 # Add a new book
29 add_new_book(
30 session,
31 author_name="Stephen King",
32 book_title="The Stand",
33 publisher_name="Random House",
34 )
35 # Output the updated hierarchical author data
36 authors = get_authors(session)
37 output_author_hierarchy(authors)
38 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
1def get_books_by_publishers(session,
ascending=True):
2 """Get a list of publishers and the number of
books they've published"""
3 if not isinstance(ascending, bool):
4 raise ValueError(f"Sorting value invalid:
{ascending}")
5
6 direction = asc if ascending else desc
7
8 return (
9 session.query(
10 Publisher.name,
func.count(Book.title).label("total_books")
11 )
12 .join(Publisher.books)
13 .group_by(Publisher.name)
14 .order_by(direction("total_books"))
15 )
39 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Line 15 closes the object, executes the query, and returns the
results to the caller.
All the above code expresses what is wanted rather than how
it’s to be retrieved. Now instead of using SQL to describe what’s
wanted, you’re using Python objects and methods. What’s
returned is a list of Python objects instead of a list of tuples of
data.
def get_authors_by_publishers(session,
ascending=True):
"""Get a list of publishers and the number of
authors they've published"""
if not isinstance(ascending, bool):
raise ValueError(f"Sorting value invalid:
{ascending}")
40 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
return (
session.query(
Publisher.name,
func.count(Author.first_name).label("total_authors"),
)
.join(Publisher.authors)
.group_by(Publisher.name)
.order_by(direction("total_authors"))
)
def get_authors(session):
"""Get a list of author objects sorted by last
name"""
return
session.query(Author).order_by(Author.last_name).all
41 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
42 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
already exist?
20 if book is not None:
21 return
22
23 # Get the book by the author
24 book = (
25 session.query(Book)
26 .join(Author)
27 .filter(Book.title == book_title)
28 .filter(
29 and_(
30 Author.first_name == first_name,
Author.last_name == last_name
31 )
32 )
33 .one_or_none()
34 )
35 # Create the new book if needed
36 if book is None:
37 book = Book(title=book_title)
38
39 # Get the author
40 author = (
41 session.query(Author)
42 .filter(
43 and_(
44 Author.first_name == first_name,
Author.last_name == last_name
45 )
46 )
47 .one_or_none()
48 )
43 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
44 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
if it does.
45 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Second, all the creations and updates happen within the context
of the session object. None of that activity is touching the
database. Only when the session.commit() statement
executes does the session then go through its unit of work and
commit that work to the database.
46 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
47 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Though not necessary for this example, a .env file holds the
environment variables for the application. The .env file exists to
contain sensitive information like passwords, which you should
keep out of your code files. However, the content of the project
.env file is shown below since it doesn’t contain any sensitive
data:
SECRET_KEY = "you-will-never-guess"
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLAlCHEMY_ECHO = False
DEBUG = True
48 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
49 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Here’s the Jinja2 HTML template that generates the home page
of the application:
50 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
21 </tr>
22 </thead>
23 <tbody>
24 {% for artist in artists %}
25 <tr>
26 <td>
27 <a href="
{{url_for('albums_bp.albums',
artist_id=artist.artist_id)}}">
28 {{ artist.name }}
29 </a>
30 </td>
31 </tr>
32 {% endfor %}
33 </tbody>
34 </table>
35 </div>
36</div>
37{% endblock %}
51 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
names.
52 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
23 name = StringField(
24 label="Artist's Name", validators=
[InputRequired(), does_artist_exist]
25 )
26
27@artists_bp.route("/")
28@artists_bp.route("/artists", methods=["GET",
"POST"])
29def artists():
30 form = CreateArtistForm()
31
32 # Is the form valid?
33 if form.validate_on_submit():
34 # Create new artist
35 artist = Artist(name=form.name.data)
36 db.session.add(artist)
37 db.session.commit()
38 return
redirect(url_for("artists_bp.artists"))
39
40 artists =
db.session.query(Artist).order_by(Artist.name).all()
41 return render_template("artists.html",
artists=artists, form=form,)
53 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
You can also create a web server providing a REST API. This
kind of server offers URL endpoints responding with data, often
in JSON format. A server providing REST API endpoints can be
used by JavaScript single-page web applications through the
54 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
Conclusion
55 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
You can get all of the code and data you saw in this tutorial at
the link below:
Further Reading
Migrating data and being able to roll back using Flask with
Postgres and SQLAlchemy is an integral part of the Software
Development Life Cycle (SDLC). You can learn more about it by
checking out Flask by Example – Setting up Postgres,
SQLAlchemy, and Alembic.
56 of 57 26/05/2022, 23:12
Data Management With Python, SQLite, and SQLAlchemy about:reader?url=https%3A%2F%2Ffanyv88.com%3A443%2Fhttps%2Frealpython.com%2Fpython-sqlite-...
57 of 57 26/05/2022, 23:12