Skip to content

Introduction

This section covers including an area in which a logged-in user can manage their own profile, with features like resetting their password, providing them a summary of posts and comments that they have created and updating their profile image.

We'll use the same styling as the admin section. To get started let's first create a simple view to render a user profile page, add the new templates, using the same style sheets as the site admin pages:

mkdir web/templates/profile
web/templates/profile/_base.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Simple Responsive Admin</title>
    <link href="/static/admin/css/bootstrap.css" rel="stylesheet"/>
    <link href="/static/admin/css/font-awesome.css" rel="stylesheet"/>
    <link href="/static/admin/css/custom.css" rel="stylesheet"/>
    <link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'/>
</head>
<body>

<div id="wrapper">
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="adjust-nav">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".sidebar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <span class="logout-spn">
                  <a href="/" style="color:#fff;">HOME</a>
                </span>
            </div>
            <span class="logout-spn">
              <a href="/auth/logout" style="color:#fff;">LOGOUT</a>
            </span>
        </div>
    </div>
    <nav class="navbar-default navbar-side" role="navigation">
        <div class="sidebar-collapse">
            <ul class="nav" id="main-menu">
                {% if context.page == "profile" %}
                <li class="active-link">
                    <a href="/admin/profile"><i class="fa fa-desktop"></i>Profile</a>
                </li>
                {% else %}
                <li>
                    <a href="/admin/profile"><i class="fa fa-desktop"></i>Profile</a>
                </li>
                {% endif %}
            </ul>
        </div>
    </nav>

    {% block content %}
    {% endblock %}

</div>
<div class="footer">
    <div class="row">
        <div class="col-lg-12">
            © 2023 exampleforyou.net | Design by: <a href="http://binarytheme.com" style="color:#fff;"
                                                          target="_blank">www.binarytheme.com</a>
        </div>
    </div>
</div>
<script src="/static/admin/js/jquery-1.10.2.js"></script>
<script src="/static/admin/js/bootstrap.min.js"></script>
<script src="/static/admin/js/custom.js"></script>
</body>
</html>
web/templates/profile/profile.html

{% extends "profile/_base.html" %}

{% block content %}

<div id="page-wrapper">
    <div id="page-inner">
        <div class="row">
            <div class="col-md-12">
                <h2>Your Profile</h2>
            </div>
        </div>
        <hr/>
    </div>
</div>

{% endblock %}

Create a new view file for user profile views:

web/views/profile_views.py
from fastapi import APIRouter, status, Request, Depends
from sqlmodel import Session

from starlette.responses import HTMLResponse, RedirectResponse
from starlette.templating import Jinja2Templates

from api.auth_apis import is_user

from db.db import get_session_db

router = APIRouter()

templates = Jinja2Templates('web/templates')


@router.get('/admin/profile', response_class=HTMLResponse, status_code=status.HTTP_200_OK)
async def profile_view(*, request: Request, session: Session = Depends(get_session_db)):
    current_user = await is_user(request, session)
    if current_user is None:
        return RedirectResponse(url='/', status_code=status.HTTP_302_FOUND)

    context = {
        "page": "profile",
        "user": current_user
    }

    return templates.TemplateResponse(
        'profile/profile.html',
        {'request': request, 'context': context},
    )

As usual we need to plumb in this new profile view in main.py:

web/views/profile_views.py
from web.views import profile_views
main_app.include_router(profile_views.router, tags=["web_views"])

!!! Tip: Remember you need to be logged in to access the user profile page!

Nothing new here yet, head to https://localhost/admin/profile to see the empty profile page.

User Profile:

screenshot

Add a new menu item for logged-in users to make it easier to access this profile page, for example in the if context.userblock:

web/templates/_base.html
                <li>
                    <a href="/admin/profile">Profile</a>
                </li>