Skip to content

Commit fa4f3fe

Browse files
committed
Demonstrate JOINs via ORM.
1 parent 0be6586 commit fa4f3fe

File tree

5 files changed

+139
-77
lines changed

5 files changed

+139
-77
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from database import session
22
from sqlalchemy_tutorial.part3_relationships.models import Comment, Post, User
33

4-
from .joins import get_posts
5-
from .orm import create_comment, create_post, create_users
4+
from .joins import list_all_comments
5+
from .objects import create_comment_objects, create_post_object, create_user_objects
6+
from .orm import create_comment, create_new_user, create_post
67

78

89
def create_relationships():
@@ -11,36 +12,24 @@ def create_relationships():
1112
1213
:return: None
1314
"""
14-
admin_user = User(
15-
username="toddthebod",
16-
password="Password123lmao",
17-
18-
first_name="Todd",
19-
last_name="Birchard",
20-
bio="I write tutorials on the internet.",
21-
avatar_url="https://storage.googleapis.com/hackersandslackers-cdn/authors/[email protected]",
22-
role="admin",
23-
)
24-
regular_user = User(
25-
username="obnoxioustroll69",
26-
password="Password123rofl",
27-
28-
first_name="Chad",
29-
last_name="Bowswick",
30-
bio="I leave hurtful comments on coding tutorials I find on the internet.",
31-
avatar_url="https://storage.googleapis.com/hackersandslackers-cdn/authors/[email protected]",
32-
)
33-
post = Post(
34-
author_id=admin_user.id,
35-
slug="fake-post-slug",
36-
title="Fake Post Title",
37-
status="published",
38-
summary="A fake post to have some fake comments.",
39-
feature_image="https://hackersandslackers-cdn.storage.googleapis.com/2021/01/[email protected]",
40-
body="Cheese slices monterey jack cauliflower cheese dolcelatte cheese and wine fromage frais rubber \
41-
cheese gouda. Rubber cheese cheese and wine cheeseburger cheesy grin paneer paneer taleggio caerphilly. \
42-
Edam mozzarella.",
43-
)
44-
admin_user, regular_user = create_users(session, admin_user, regular_user)
45-
new_post = create_post(session, post, admin_user)
46-
create_comment(session, regular_user, new_post)
15+
# Create admin & regular user
16+
admin_user, regular_user = create_user_objects()
17+
admin_user = create_new_user(session, admin_user)
18+
regular_user = create_new_user(session, regular_user)
19+
20+
# Create post object and add to database
21+
post = create_post_object(admin_user)
22+
post = create_post(session, post, admin_user)
23+
24+
# Create three comments on the same post
25+
(
26+
comment_1,
27+
comment_2,
28+
comment_3,
29+
) = create_comment_objects(regular_user, post)
30+
create_comment(session, regular_user, comment_1)
31+
create_comment(session, regular_user, comment_2)
32+
create_comment(session, regular_user, comment_3)
33+
34+
# Show post with comments:
35+
list_all_comments(session)

sqlalchemy_tutorial/part3_relationships/joins.py

+17-7
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,29 @@
22
from sqlalchemy.orm import Session
33

44
from logger import LOGGER
5-
from sqlalchemy_tutorial.part3_relationships.models import Post
5+
from sqlalchemy_tutorial.part3_relationships.models import Comment, Post
66

77

8-
def get_posts(session: Session):
8+
def list_all_comments(session: Session):
99
"""
10-
Fetch posts.
10+
Fetch all comments and join with their parent posts.
1111
1212
:param session: SQLAlchemy database session.
1313
:type session: Session
1414
1515
:return: None
1616
"""
17-
posts = session.query(Post).all()
18-
for post in posts:
19-
LOGGER.info(f"Post: {post}")
20-
LOGGER.info(f"Post author: {post.author}")
17+
comments = session.query(Comment).join(Post, Post.id == Comment.post_id).all()
18+
for comment in comments:
19+
comment_record = {
20+
"comment_id": comment.id,
21+
"body_summary": f"{comment.body[:50]}...",
22+
"upvotes": comment.upvotes,
23+
"comment_author_id": comment.user_id,
24+
"post": {
25+
"slug": comment.post.slug,
26+
"title": comment.post.title,
27+
"post_author": comment.post.author.username,
28+
},
29+
}
30+
LOGGER.info(comment_record)

sqlalchemy_tutorial/part3_relationships/models.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Comment(Base):
3838

3939
id = Column(Integer, primary_key=True, index=True)
4040
user_id = Column(Integer, ForeignKey("user.id"))
41-
post_id = Column(Integer, index=True)
41+
post_id = Column(Integer, ForeignKey("post.id"), index=True)
4242
body = Column(Text)
4343
upvotes = Column(Integer, default=1)
4444
removed = Column(Boolean, default=False)
@@ -69,6 +69,7 @@ class Post(Base):
6969

7070
# Relationships
7171
author = relationship("User", backref="posts")
72+
comments = relationship("Comment", backref="post")
7273

7374
def __repr__(self):
7475
return "<Post %r>" % self.slug
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
"""Initialize objects from data models to generate in Database."""
2+
from typing import Tuple
3+
4+
from sqlalchemy_tutorial.part3_relationships.models import Comment, Post, User
5+
6+
7+
def create_user_objects() -> Tuple[User, User]:
8+
"""
9+
Set up an admin user to own a `Post`, and regular user to add comments.
10+
11+
:return: Tuple[User, User]
12+
"""
13+
admin_user = User(
14+
username="toddthebod",
15+
password="Password123lmao",
16+
17+
first_name="Todd",
18+
last_name="Birchard",
19+
bio="I write tutorials on the internet.",
20+
avatar_url="https://storage.googleapis.com/hackersandslackers-cdn/authors/[email protected]",
21+
role="admin",
22+
)
23+
regular_user = User(
24+
username="obnoxioustroll69",
25+
password="Password123rofl",
26+
27+
first_name="Chad",
28+
last_name="Bowswick",
29+
bio="I leave hurtful comments on coding tutorials I find on the internet.",
30+
avatar_url="https://storage.googleapis.com/hackersandslackers-cdn/authors/[email protected]",
31+
)
32+
return admin_user, regular_user
33+
34+
35+
def create_post_object(admin_user: User) -> Post:
36+
"""
37+
Set up post to add to database.
38+
39+
:param admin_user: User to serve as post author.
40+
:type admin_user: User
41+
42+
:return: Post
43+
"""
44+
return Post(
45+
author_id=admin_user.id,
46+
slug="fake-post-slug",
47+
title="Fake Post Title",
48+
status="published",
49+
summary="A fake post to have some fake comments.",
50+
feature_image="https://hackersandslackers-cdn.storage.googleapis.com/2021/01/[email protected]",
51+
body="Cheese slices monterey jack cauliflower cheese dolcelatte cheese and wine fromage frais rubber \
52+
cheese gouda. Rubber cheese cheese and wine cheeseburger cheesy grin paneer paneer taleggio caerphilly. \
53+
Edam mozzarella.",
54+
)
55+
56+
57+
def create_comment_objects(
58+
regular_user: User, post: Post
59+
) -> Tuple[Comment, Comment, Comment]:
60+
"""
61+
Set up 3 comments to be added to published post.
62+
63+
:param regular_user: User to serve as comment author.
64+
:type regular_user: User
65+
:param post: Blog post to be created.
66+
:type post: Post
67+
68+
:return: Tuple[Comment, Comment, Comment]
69+
"""
70+
comment_1 = Comment(
71+
user_id=regular_user.id,
72+
post_id=post.id,
73+
body="This post about SQLAlchemy is awful. You didn't even bother to explain how to install Python, \
74+
which is where I (and so many others) got stuck. Plus, your code doesn't even work!! \
75+
I cloned your code and it keeps giving me `environment variable` errors... \
76+
WTF are environment variables?!!?!?",
77+
upvotes=2,
78+
)
79+
comment_2 = Comment(
80+
user_id=regular_user.id,
81+
post_id=post.id,
82+
body="By the way, you SUCK!!! I HATE you!!!! I have a project due tomorrow, how am I supposed to finish \
83+
if you won't do my job for me, you selfish prick?!?!",
84+
upvotes=5,
85+
)
86+
comment_3 = Comment(
87+
user_id=regular_user.id,
88+
post_id=post.id,
89+
body="YOU RUINED MY LIFE!!!!",
90+
upvotes=5,
91+
)
92+
return comment_1, comment_2, comment_3

sqlalchemy_tutorial/part3_relationships/orm.py

+4-34
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,6 @@
88
from sqlalchemy_tutorial.part3_relationships.models import Comment, Post, User
99

1010

11-
def create_users(
12-
session: Session, admin_user: User, regular_user: User
13-
) -> Tuple[User, User]:
14-
"""
15-
Create a couple of user accounts.
16-
17-
:param session: SQLAlchemy database session.
18-
:type session: Session
19-
:param admin_user: User model representing admin user to be created.
20-
:type admin_user: User
21-
:param regular_user: User model representing non-admin user to be created.
22-
:type regular_user: User
23-
24-
:return: Tuple[User, User]
25-
"""
26-
admin_user = create_new_user(session, admin_user)
27-
regular_user = create_new_user(session, regular_user)
28-
LOGGER.success(f"Created 2 users: {admin_user} & {regular_user}")
29-
return admin_user, regular_user
30-
31-
3211
def create_new_user(session: Session, user: User) -> User:
3312
"""
3413
Create a new user if username isn't already taken.
@@ -65,7 +44,7 @@ def create_post(session: Session, post: Post, admin_user: User) -> Post:
6544
:type session: Session
6645
:param post: Blog post to be created.
6746
:type post: Post
68-
:param admin_user: User to serve as post author.
47+
:param admin_user: User to serve as post or comment author.
6948
:type admin_user: User
7049
7150
:return: Post
@@ -93,29 +72,20 @@ def create_post(session: Session, post: Post, admin_user: User) -> Post:
9372
raise e
9473

9574

96-
def create_comment(session: Session, regular_user: User, post: Post) -> Comment:
75+
def create_comment(session: Session, regular_user: User, comment: Comment) -> Comment:
9776
"""
9877
Create a comment posted by `regular_user` on `admin_user`'s post.
9978
10079
:param session: SQLAlchemy database session.
10180
:type session: Session
10281
:param regular_user: User to serve as comment author.
10382
:type regular_user: User
104-
:param post: Blog post to be commented on.
105-
:type post: Post
83+
:param comment: User comment left on published post.
84+
:type comment: Comment
10685
10786
:return: Comment
10887
"""
10988
try:
110-
comment = Comment(
111-
user_id=regular_user.id,
112-
post_id=post.id,
113-
body="This post about SQLAlchemy is awful. You didn't even bother to explain how to install Python, \
114-
which is where I (and so many others) got stuck. Plus, your code doesn't even work!! \
115-
I cloned your code and it keeps giving me `environment variable` errors... \
116-
WTF are environment variables?!!?!?",
117-
upvotes=2,
118-
)
11989
session.add(comment) # Add the Comment
12090
session.commit() # Commit the change
12191
LOGGER.success(f"Created comment {comment} posted by user {regular_user}")

0 commit comments

Comments
 (0)