rust actix_web + tera tamplates给予me [actix_web::data]无法提取< tera::tera::Tera>“index”处理程序的“Data”,请使用“Data::new()” Package 数据

e0bqpujr  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(124)

我试着让actix-webTera一起工作,从我在网上找到的例子。
这是我的代码:

use actix_web::{get, web, Result, App, HttpServer, HttpRequest, Responder, HttpResponse};
use serde::{Deserialize,Serialize};
use tera::{Tera, Context};
use lazy_static::lazy_static;

lazy_static! {
    pub static ref TEMPLATES: Tera = {
        let mut tera = match Tera::new("templates/**/*.html") {
            Ok(t) => t,
            Err(e) => {
                println!("Parsing error(s): {}", e);
                ::std::process::exit(1);
            }
        };
        tera.autoescape_on(vec![".html", ".sql"]);
        tera
    };
}

#[derive(Serialize)]
pub struct Response {
    pub message: String,
}

#[get("/")]
async fn index(tera: web::Data<Tera>) -> impl Responder {
    let mut context = Context::new();
    let template = tera.render("test.page.html", &context).expect("Error");
    HttpResponse::Ok().body(template)
}

async fn not_found() -> Result<HttpResponse> {
    let response = Response {
        message: "Resource not found".to_string(),
    };
    Ok(HttpResponse::NotFound().json(response))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    std::env::set_var("RUST_LOG", "debug");
    env_logger::init();
    HttpServer::new(|| App::new()
        .service(index)
        .default_service(web::route().to(not_found)))
        .bind(("127.0.0.1", 9090))?
        .run()
        .await        
}

但是当我访问url时,我得到了这个错误:

[2023-08-29T11:27:53Z INFO  actix_server::builder] starting 8 workers
[2023-08-29T11:27:53Z INFO  actix_server::server] Actix runtime found; starting in Actix runtime
[2023-08-29T11:28:07Z DEBUG actix_web::data] Failed to extract `Data<tera::tera::Tera>` for `index` handler. For the Data extractor to work correctly, wrap the data with `Data::new()` and pass it to `App::app_data()`. Ensure that types align in both the set and retrieve calls.

为什么要用Data::new()封装,而使用App::app_data()

snz8szmq

snz8szmq1#

为什么要用Data::new()封装它并使用App::app_data()
因为如果不知道的话Actix就不能把提取器交给你的接头人。
由于您已经使用了一个lazy_static来拥有Tera的一个示例,因此您不需要将其作为提取器传递给处理程序-只需使用静态!

#[get("/")]
async fn index() -> impl Responder {
    let mut context = Context::new();
    let template = TEMPLATES.render("test.page.html", &context).expect("Error");
    HttpResponse::Ok().body(template)
}

但是你不需要使用lazy_static。Actix-web允许您定义共享资源,并使用提取器将其提供给每个请求。目前还不清楚您想采取哪种方法(因为您两者都做了一点!)但另一种方式,使用共享状态,是这样的:

fn create_templates() - Tera {
    let mut tera = Tera::new("templates/**/*.html").expect("failed to parse template");
    tera.autoescape_on(vec![".html", ".sql"]);
    tera
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new()
       .service(index)
       .app_data(Data::new(create_templates()))
       .default_service(web::route().to(not_found)))
       .bind(("127.0.0.1", 9090))?
       .run()
       .await        
}

#[get("/")]
async fn index(tera: web::Data<Tera>) -> impl Responder {
    let mut context = Context::new();
    let template = tera.render("test.page.html", &context).expect("Error");
    HttpResponse::Ok().body(template)
}

相关问题