首页 > 其他分享 >使用axum构建博客系统 - 模板

使用axum构建博客系统 - 模板

时间:2023-10-21 20:37:07浏览次数:33  
标签:index frontend axum rs 博客 handler 模板 页面

我们的博客分为“前台”和“后台”两部分。前台用于展示博客内容,后台用于管理博客。本章我们将编写前台和后台的基础模板以及对应的路由。

目录结构

前台模板位于 templates/frontend,后台模板位于templates/backend

前台

我们的前台模板基于 Bootstrap的Blog 修改而来

布局

首先,我们对前台页面的布局来做一个全局总览。

注意,以下示意图链接到 github,如果你无法查看,请更换网络环境

前台页面布局

  • 【页眉】显示博客名称
  • 【博客分类】从数据库中读取所有分类,并以导航栏的形式显示在页面上
  • 【关于我们】和【友情链接】本项目中,它们都是硬编码在页面上的
  • 【存档】按月份显示,点击其中的月份会跳转到显示该月份所有博客的列表页面
  • 【页脚】显示版权信息
  • 【页面标题】动态定义当前页面的标题
  • 【页面内容】动态定义当前页面的内容

母模板

基于以上对布局的说明,我们的母模板 templates/frontend/base.html需要定义两个块(block)

  • 对应【页面标题】的 {% block category_name %}分类名称{%endblock%}
  • 对应【页面内容】的{% block content%}页面内容{%endblock%}

虽然其它区域是固定的,但有些区域的内容还是需要从数据库中获取数据来填充。现阶段而言,我们只定义了【页面标题】对应的块,其它区域都保持硬编码的文字。

首页模板

有了母模板,我们就可以通过extends来衍生出业务需要的特定模板了,比如现阶段我们定义的首页的模板:

<!-- templates/frontend/index.html -->
{%extends "./base.html"%}
{%block category_name%}最新博文{%endblock%}

视图类

下面,我们为前台首页定义一下视图类:

// src/view/frontend/index.rs
use askama::Template;

#[derive(Template)]
#[template(path="frontend/index.html")]
pub struct Index {}

handler

有了视图类,就可以将模板进行渲染:

// src/handler/frontend/index.rs

pub async fn index()->Result<HtmlView> {
    let handler_name = "frontend/index/index";
    let tmpl = Index{};
    render(tmpl).map_err(log_error(handler_name))
}

在这个 handler 中,出现了几个新元素:

  • HtmlView:自定义的类型,用于返回HTML视图
  • render():用于通过视图类来渲染模板
  • log_error():使用日志记录AppError

它们的代码实现如下:

HtmlView

// src/handler/mod.rs

type HtmlView = axum::response::Html<String>;

render()

// src/handler/mod.rs

fn render<T>(tmpl: T) ->Result<HtmlView> where T:Template {
    let html = tmpl.render().map_err(AppError::from)?;
    Ok(Html(html))
}

泛型T必须满足askama::Template约束。由于我们定义视图类的时候使用了 #[derive(Template)],所以我们的视图类满足这一约束。

该函数用于渲染模板,模板文件的路径通过视图类的#[template(path="frontend/index.html")]指定。默认模板引擎会在项目根目录的templates目录下,查找path指定的模板文件。

如果发生错误,通过map_err将其转换为AppError

log_error()

// src/handler/mod.rs

fn log_error(handler_name:&str) -> Box<dyn Fn(AppError)->AppError> {
     let handler_name = handler_name.to_string();
     Box::new(move |err| {
         tracing::error!("操作失败:{:?},  {}", err, handler_name);
         err
     })
 }

该函数用于记录产生的AppError日志。

路由

我们还需要定义路由。

// src/handler/frontend/mod.rs

pub fn router()->Router {
     Router::new().route("/", get(index::index))
}

后台

我们的后台模板基于 Bootstrap的Dashboard 修改而来

布局

我们来看一下后台页面的布局:

后台页面布局

  • 【页眉】显示应用名称以【退出登录】链接
  • 【侧边菜单】显示可用的菜单
  • 【页面标题】显示当前页面的标题
  • 【工具栏】显示当前页面可用的工具栏
  • 【提示信息】该区域和【页面内容】平行,示意图上没有画出。用于显示提示信息。
  • 【页面内容】显示当前页面的内容
  • 【分页】如果需要分页,则这里显示分页按钮

母模板

通过以上分析,我们需要定义以下块:

  • 【页面标题】:{% block title%}标题{%endblock%}
  • 【工具栏】:{% block toolbar %}{%endblock%} 
  • 【提示信息】 {% block msg%} {%endblock%}
  • 【页面内容】{%block content%}内容{%endblock%}

当然,现阶段而言,我们并不需要定义它们,随着项目的推进,会对其进行补全。

首页模板

根据母模板,我们来定义后台首页模板:

<!-- templates/backend/index.html -->

 {% extends "./base.html" %}

视图类

// src/view/backend/index.rs

use askama::Template;

#[derive(Template)]
#[template(path="backend/index.html")]
pub struct Index {}

handler

// src/handler/backend/index.rs

pub async fn index()->Result<HtmlView>{
let handler_name="backend/index/index";
    let tmpl = Index{};
    render(tmpl).map_err(log_error(handler_name))
}

路由

// src/handler/backend/mod.rs

pub fn router() -> Router {
    Router::new().route("/", get(index))
}

启动axum服务

// src/main.rs

use axum::Router;
use axum_rs_blog::handler::{backend, frontend};

#[tokio::main]
async fn main() {
    if std::env::var_os("RUST_LOG").is_none() {
        std::env::set_var("RUST_LOG", "axum_rs_blog=debug");
    }
    tracing_subscriber::fmt::init();

    tracing::info!("服务已启动");

    let frentend_routers = frontend::router();
    let backend_routers = backend::router();
    let app = Router::new()
        .nest("/", frentend_routers)
        .nest("/admin", backend_routers);

    axum::Server::bind(&"127.0.0.1:9527".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

标签:index,frontend,axum,rs,博客,handler,模板,页面
From: https://www.cnblogs.com/pythonClub/p/17779451.html

相关文章

  • 使用axum构建博客系统 - 分类管理
    本章开始,我们将对博客的具体业务进行实现。首先,我们实现博客分类的管理功能。数据库结构CREATETABLEcategories(idSERIALPRIMARYKEY,nameVARCHAR(100)NOTNULL,is_delBOOLEANNOTNULLDEFAULTFALSE);字段说明id主键。唯一标识,自增长。name分......
  • 使用axum构建博客系统 - 文章管理
    本章我们将实现博客的文章管理功能。数据库结构CREATETABLEtopics(idBIGSERIALPRIMARYKEY,titleVARCHAR(255)NOTNULL,category_idINTNOTNULL,summaryVARCHAR(255)NOTNULL,markdownVARCHARNOTNULL,htmlVARCHARNOTNULL,hitINTNOTNUL......
  • 使用axum构建博客系统 - 后台管理菜单及首页模板
    目前,后台管理功能基本完成,但还有两个工作没做:清理后台管理的导航菜单以及后台管理首页的模板。后台管理菜单<!--templates/backend/base.html--><!--...--><divclass="container-fluid"><divclass="row"><navid="sidebarMenu"c......
  • 使用axum构建博客系统 - 鉴权与登录
    本章实现后台管理的鉴权,以及管理员的登录、注销功能。涉及的知识点有:cookie及中间件等。数据库结构CREATETABLEadmins(idSERIALPRIMARYKEY,emailVARCHAR(255)NOTNULL,passwordVARCHAR(255)NOTNULL,is_delBOOLEANNOTNULLDEFAULTFALSE);字段说......
  • 使用axum构建博客系统 - 网站首页
    后台管理完成后,我们开始进入前台功能的开发。本章我们将完成博客首页的开发。母模板templates/frontend/base.html是时候对前台母模板进行数据填充和块的定义了:<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="utf-8"/><metaname="viewport"c......
  • 使用axum构建博客系统 - 分类文章列表
    本章将实现博客的分类文章列表功能。模板请参见代码仓库的templates/frontend/topic_list.html视图类请参见代码仓库的src/view/frontend/topic.rshandler//src/handler/frontend/topic.rspubasyncfnlist(Extension(state):Extension<Arc<AppState>>,Path(......
  • 使用axum构建博客系统 - 文章详情
    本章将实现博客文章的详情显示功能。数据库视图CREATEVIEWv_topic_cat_detailASSELECTt.id,title,html,hit,dateline,category_id,t.is_del,c.nameAScategory_nameFROMtopicsAStINNERJOINcategoriesAScONt.cate......
  • 使用axum构建博客系统 - 存档文章列表
    本章将实现存档文章列表功能。注意,本章涉及较多PostgreSQL知识,如果你对相关知识不熟悉,可以先让代码跑起来,再去了解相关知识。模板本功能模板文件是templates/frontend/topic_arch.html。视图类本功能视图类定义在src/view/frontend/topic.rs文件。handler//src/handler/fro......
  • 巧用模板字符串将未知变量转换为string类型,避免报错
    可理解为将变量向字符串类型转换的语法糖用法我们通常会遇到需要用String.prototype上的方法处理变量,如果该变量为null、undefined、Object则不能直接用字符串方法,也不易于统一处理为字符串;使用模板字符串包裹该变量,则可以简单粗暴的将任意类型转换为字符串类型,避免报错。案例:......
  • 每日博客
    1.Hive是由Facebook公司开发的一个构建在Hadoop之上的数据仓库工具,在某种程度上可以看作是用户编程接口,其本身并不存储和处理数据2.Hive一般依赖于分布式文件系统HDFS,而传统数据库则依赖于本地文件系统,Hive和传统关系数据库都支持分区,传统关系数据库很难实现横向扩展,Hive具......