Example: blog post and comments

Let’s create a simple blog posts databases with comments. You’ll need to create:

  • a Post model with title, tags and content fields

  • a Comment wich is linked to Post

Why to not add a “comments” field inside Post Model ? Actually, you can. But there are 3 majors troubles that may happen:

  • Create a “comment” means to “update” the post object, and so… you’ll change the “updated_at” value

  • Its possible (but not probable) that you can write a post at the same time as a comment, so one will overwrite the other

  • And, if you’ve got a lot of comments for a post, the post object will be heavy

So, it’s more efficient to link post inside the comments, and not comments inside the posts.

Warning

In this case, cascading deletion should not be used. Deleting a blog post will not delete children comments. And if you set Cascade attribute to “post” on the comment object, you will remove the post when a comment is deleted. Keep in mind that the cascading deletion should only be ativate from the parent !

This is the model:

from typing import Optional, List
from rethinkmodel import Model
from rethtinkmodel.transforms import Linked
from rethtinkmodel.checkers import NonNull

class Post(Model)
    title: str
    content: Optional[str]
    tags: List[str]

class Comment(Model)
    author: str
    content: str
    post: Type[Post] # make the link to Post

Now, let’s create a blog post.

post = Post(
    title="My first post",
    content="This is the content",
    tags=["example", "article"],
)
post.save()

In database, you can find the article. The “post.id” field is set (uuid form), and you can use it to add a comments.

comment = Comment(
    author="Bob",
    content="Nice post dude",
    post=post
)
comment.save()

Inside RethinkDB database the comment object contains the post.id value. But when you will get it, RethinkModel will fetches the linked object. That means that you can get the title of the article by calling:

comment.post.title

Now, how to get comments from a post ? The easiest method is to use join() method:

post = Post.get(post_id).join(Comment)
post.comments # contains the Comment objects list

Danger

The joined attribute is set from the joined tablename as described in your model. If you declared a propoerty with that name, it will be overwritten at fetch time. If you save the parent object, so you will write data. It is possible that Rethink:Model will prevent this later.

# If you do this:
class Post(Model):
    #...
    comments: Any

# Then
Post.get(post_id).Join(Comment)
# the post.comments property is reset by the joined data.

You may also use filter method to get comment list from a post ID:

comments = Comment.filter({
    "post" : post.id
})

The comments variable is a list that contains comments for the post. The post atribute of the entire comment list will be filled by the corresponding Post object.

You can update them and use save method as they have got “id”. The updated_at attribute will be automatically updated.