Git Commit: feature to create a blog
To enable creating a blog post we would need a form that lets our end users enter the title and content of a new blog. To support this, we would need to create a form similar to login in templates > blog > create_blog.html
{% extends "base.html" %}
{% block title %}
<title>Write a Blog</title>
{% endblock %}
{% block content %}
{% for error in errors %}
<div class="alert alert-danger">
<li>{{error}}</li>
</div>
{% endfor %}
<div class="container">
<div class="text-center display-4">Write a Blog</div>
<div class="row mt-3 mb-5">
<div class="col-3"></div>
<div class="col-6">
<form method="POST">
<label>Title</label>
<input type="text" required class="form-control mb-2" name="title" value="{{title}}" placeholder="Enter a Title">
<label>Content</label>
<textarea name="content" class="form-control mb-2">{{content}}</textarea>
<button type="submit" class="btn btn-outline-success">Submit for Review</button>
</form>
</div>
<div class="col-3"></div>
</div>
</div>
{% endblock %}
In order to show the above form, we would need to implement a route for GET request. When the form would be submitted, we would get a POST request. So, we would need one more route for post request.
from typing import Optional
from db.repository.blog import list_blogs
from db.repository.blog import retreive_blog
from db.session import get_db
from fastapi import APIRouter
from fastapi import Depends
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
from fastapi import Request
from fastapi import Form, responses, status #new imports
from fastapi.security.utils import get_authorization_scheme_param
from schemas.blog import CreateBlog
from apis.v1.route_login import get_current_user
from db.repository.blog import create_new_blog
templates = Jinja2Templates(directory="templates")
router = APIRouter()
###
@router.get("/app/create-new-blog")
def create_blog(request: Request):
return templates.TemplateResponse("blog/create_blog.html",{"request":request})
@router.post("/app/create-new-blog")
def create_blog(
request: Request,
title: str = Form(...),
content: str = Form(...),
db: Session = Depends(get_db),
):
token = request.cookies.get("access_token")
_, token = get_authorization_scheme_param(token)
try:
author = get_current_user(token=token, db=db)
blog = CreateBlog(title=title, content=content)
blog = create_new_blog(blog=blog, db=db, author_id=author.id)
return responses.RedirectResponse(
"/?alert=Blog Submitted for Review", status_code=status.HTTP_302_FOUND
)
except Exception as e:
errors = ["Please log in to create blog"]
print("Exception raised", e)
return templates.TemplateResponse(
"blog/create_blog.html",
{"request": request, "errors": errors, "title": title, "content": content},
)
This is again very simple, we extract token from the cookies. The get_authorization_scheme_param function returns a tuple of ("Bearer", "token_value"). We take the token value and use the get_current_user function to get the user corresponding to the token. It might so, happen that token is expired or tampered with. In such cases, we return the same form with the error message and the previously filled-in values. (This is very important for user experience! I have gotten irritated quite a few times when my form data is lostðŸ˜)
Then we follow the same procedure that we followed in the API. We created a pydantic schema of the blog and passed it to our repository function to create the blog. If everything worked fine, we are redirecting to the homepage with an alert message.
Brige the gap between Tutorial hell and Industry. We want to bring in the culture of Clean Code, Test Driven Development.
We know, we might make it hard for you but definitely worth the efforts.
© Copyright 2022-23 Team FastAPITutorial