域名 AXUM.RS 将于 2025 年 10 月到期。我们无意再对其进行续费,如果你有意接续这个域名,请与我们取得联系。
  • AXUM.RS 现仅需人民币 3000 元(大写:叁仟元整。接受适度议价
  • 按照行业规则,AXUM.RS 到期后,大概率会进入长时间的赎回期,该期间内,如果你想拥有该域名,将要付出高额的费用
  • 我们已启用 AXUM.EU.ORG 域名,并将持续运营
  • 仅接受微信或支付宝交易
如果你对 AXUM.RS 有兴趣,请和我们进行联系:

文章详情

数据库视图

CREATE VIEW v_topic_cat_detail AS
  SELECT t.id, title, html, hit, dateline,category_id,t.is_del,
         c.name AS category_name
    FROM
      topics AS t
      INNER JOIN categories AS c
          ON t.category_id=c.id
   WHERE c.is_del = false
         ;

该视图和v_topic_cat_list唯一不同的地方在于,它要的是topicshtml字段。

数据模型

// src/model.rs
#[derive(PostgresMapper, Serialize)]
#[pg_mapper(table="v_topic_cat_detail")]
pub struct TopicDetail{
    pub id:i64,
    pub title: String,
    pub category_id:i32,
    pub html:String,
    pub hit:i32,
    pub dateline:time::SystemTime,
    pub is_del:bool,
    pub category_name:String,
}
impl TopicDetail {
    pub fn dateline(&self) ->String {
        dateline(self.dateline.clone())
    }
}

fn dateline(dt:time::SystemTime) -> String {
    let ts = dt.duration_since(time::UNIX_EPOCH).unwrap_or(time::Duration::from_secs(0)).as_secs() as i64;
    Local.timestamp(ts, 0).format("%Y/%m/%d %H:%M:%S").to_string()
}
// src/model.rs
impl TopicList {
    pub fn dateline(&self) ->String {
        dateline(self.dateline.clone())
    }
}

模板

文章详情的模板位于templates/frontend/topic_detail.html,请自行查看。

视图类

文章详情的视图类位于src/view/frontend/topic.rs,请自行查看。

handler

topic::detail()用于通过id获取文章详情。

数据库操作

首先,使文章的浏览次数加1,然后返回文章的数据。

前面章节说过,Postgresql支持RETURNING,为什么此处要写两句SQL?

原因在于,我们需要返回的数据来自于视图,如果:

另外,此处不需要用事务,因为如果UPDATE出错,那么整个函数都退出了(返回值是Err(AppError))——除非你把SELECT写在UPDATE前面。

路由

本功能的路由定义在src/handler/frontend/mod.rs文件。

本章代码位于09/文章详情分支。

要查看完整内容,请先登录