From 8f3a45e6aeb8683e6f8553b9f38c4cf1f5b78064 Mon Sep 17 00:00:00 2001 From: Sam Samai Date: Sun, 12 Sep 2021 10:07:00 +1000 Subject: [PATCH] Use tera template and serve static assets --- examples/actix_example/Cargo.toml | 4 +- examples/actix_example/src/main.rs | 316 +++--------------- examples/actix_example/src/post.rs | 8 +- .../actix_example/templates/base.html.tera | 81 ----- .../actix_example/templates/edit.html.tera | 50 --- .../actix_example/templates/index.html.tera | 110 +++--- .../actix_example/templates/new.html.tera | 38 --- .../rocket_example/templates/base.html.tera | 63 +--- 8 files changed, 115 insertions(+), 555 deletions(-) delete mode 100644 examples/actix_example/templates/base.html.tera delete mode 100644 examples/actix_example/templates/edit.html.tera delete mode 100644 examples/actix_example/templates/new.html.tera diff --git a/examples/actix_example/Cargo.toml b/examples/actix_example/Cargo.toml index 9d667677..8cf3b6c8 100644 --- a/examples/actix_example/Cargo.toml +++ b/examples/actix_example/Cargo.toml @@ -14,6 +14,7 @@ futures = { version = "^0.3" } futures-util = { version = "^0.3" } actix-http = "2" actix-web = "3" +actix-files = "0.5" tera = "1.8.0" # remove `path = ""` in your own project @@ -22,7 +23,8 @@ sea-orm = { path = "../../", version = "^0.2", features = [ "sqlx-all", "runtime-tokio-native-tls", ], default-features = false } -serde_json = { version = "^1" } +serde = "1" +env_logger = "0.8" [dependencies.sqlx] version = "^0.5" diff --git a/examples/actix_example/src/main.rs b/examples/actix_example/src/main.rs index e8f054ea..bc897541 100644 --- a/examples/actix_example/src/main.rs +++ b/examples/actix_example/src/main.rs @@ -1,40 +1,18 @@ -use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder}; +// use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder}; -#[get("/")] -async fn hello() -> impl Responder { - HttpResponse::Ok().body("Hello world!") -} -#[post("/echo")] -async fn echo(req_body: String) -> impl Responder { - HttpResponse::Ok().body(req_body) -} +use actix_http::{body::Body, Response}; +use actix_web::dev::ServiceResponse; +use actix_web::http::StatusCode; +use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers}; +use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer, Result}; +use actix_files as fs; -async fn manual_hello() -> impl Responder { - HttpResponse::Ok().body("Hey there!") -} +use tera::Tera; -#[actix_web::main] -async fn main() -> std::io::Result<()> { - HttpServer::new(|| { - App::new() - .service(hello) - .service(echo) - .route("/hey", web::get().to(manual_hello)) - }) - .bind("127.0.0.1:8080")? - .run() - .await -} +mod post; +pub use post::Entity as Post; -// use std::collections::HashMap; - -// use actix_http::{body::Body, Response}; -// use actix_web::dev::ServiceResponse; -// use actix_web::http::StatusCode; -// use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers}; -// use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer, Result}; -// use tera::Tera; // // store tera template in application state // async fn index( @@ -55,252 +33,34 @@ async fn main() -> std::io::Result<()> { // Ok(HttpResponse::Ok().content_type("text/html").body(s)) // } -// #[actix_web::main] -// async fn main() -> std::io::Result<()> { -// HttpServer::new(|| { -// App::new() -// .service(hello) -// .service(echo) -// .route("/hey", web::get().to(manual_hello)) -// }) -// .bind("127.0.0.1:8080")? -// .run() -// .await -// } +async fn list( tmpl: web::Data) -> Result { + let posts: Vec = vec!(); + let mut ctx = tera::Context::new(); + ctx.insert("posts", &posts); + ctx.insert("page", &0); + ctx.insert("num_pages", &1); + let s = tmpl.render("index.html.tera", &ctx) + .map_err(|_| error::ErrorInternalServerError("Template error"))?; + Ok(HttpResponse::Ok().content_type("text/html").body(s)) +} -// #[actix_web::main] -// async fn main() -> std::io::Result<()> { -// std::env::set_var("RUST_LOG", "actix_web=info"); -// env_logger::init(); +#[actix_web::main] +async fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); + env_logger::init(); -// println!("Listening on: 127.0.0.1:8080, open browser and visit have a try!"); -// HttpServer::new(|| { -// let tera = -// Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap(); - -// App::new() -// .data(tera) -// .wrap(middleware::Logger::default()) // enable logger -// .service(web::resource("/").route(web::get().to(index))) -// .service(web::scope("").wrap(error_handlers())) -// }) -// .bind("127.0.0.1:8080")? -// .run() -// .await -// } - -// // Custom error handlers, to return HTML responses when an error occurs. -// fn error_handlers() -> ErrorHandlers { -// ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found) -// } - -// // Error handler for a 404 Page not found error. -// fn not_found(res: ServiceResponse) -> Result> { -// let response = get_error_response(&res, "Page not found"); -// Ok(ErrorHandlerResponse::Response( -// res.into_response(response.into_body()), -// )) -// } - -// // Generic error handler. -// fn get_error_response(res: &ServiceResponse, error: &str) -> Response { -// let request = res.request(); - -// // Provide a fallback to a simple plain text response in case an error occurs during the -// // rendering of the error page. -// let fallback = |e: &str| { -// Response::build(res.status()) -// .content_type("text/plain") -// .body(e.to_string()) -// }; - -// let tera = request.app_data::>().map(|t| t.get_ref()); -// match tera { -// Some(tera) => { -// let mut context = tera::Context::new(); -// context.insert("error", error); -// context.insert("status_code", res.status().as_str()); -// let body = tera.render("error.html", &context); - -// match body { -// Ok(body) => Response::build(res.status()) -// .content_type("text/html") -// .body(body), -// Err(_) => fallback(error), -// } -// } -// None => fallback(error), -// } -// } - -// ----------------------------- -// #[macro_use] -// extern crate rocket; - -// use rocket::fairing::{self, AdHoc}; -// use rocket::form::{Context, Form}; -// use rocket::fs::{relative, FileServer}; -// use rocket::request::FlashMessage; -// use rocket::response::{Flash, Redirect}; -// use rocket::{Build, Request, Rocket}; -// use rocket_db_pools::{sqlx, Connection, Database}; -// use rocket_dyn_templates::{context, Template}; - -// use sea_orm::entity::*; - -// mod pool; -// use pool::RocketDbPool; - -// mod setup; - -// #[derive(Database, Debug)] -// #[database("rocket_example")] -// struct Db(RocketDbPool); - -// type Result> = std::result::Result; - -// mod post; -// pub use post::Entity as Post; - -// const DEFAULT_POSTS_PER_PAGE: usize = 25; - -// #[get("/new")] -// fn new() -> Template { -// Template::render("new", &Context::default()) -// } - -// #[post("/", data = "")] -// async fn create(conn: Connection, post_form: Form) -> Flash { -// let form = post_form.into_inner(); - -// post::ActiveModel { -// title: Set(form.title.to_owned()), -// text: Set(form.text.to_owned()), -// ..Default::default() -// } -// .save(&conn) -// .await -// .expect("could not insert post"); - -// Flash::success(Redirect::to("/"), "Post successfully added.") -// } - -// #[post("/", data = "")] -// async fn update(conn: Connection, id: i32, post_form: Form) -> Flash { -// let post: post::ActiveModel = Post::find_by_id(id) -// .one(&conn) -// .await -// .unwrap() -// .unwrap() -// .into(); - -// let form = post_form.into_inner(); - -// post::ActiveModel { -// id: post.id, -// title: Set(form.title.to_owned()), -// text: Set(form.text.to_owned()), -// } -// .save(&conn) -// .await -// .expect("could not edit post"); - -// Flash::success(Redirect::to("/"), "Post successfully edited.") -// } - -// #[get("/?&")] -// async fn list( -// conn: Connection, -// posts_per_page: Option, -// page: Option, -// flash: Option>, -// ) -> Template { -// let page = page.unwrap_or(0); -// let posts_per_page = posts_per_page.unwrap_or(DEFAULT_POSTS_PER_PAGE); -// let paginator = Post::find().paginate(&conn, posts_per_page); -// let num_pages = paginator.num_pages().await.ok().unwrap(); - -// let posts = paginator -// .fetch_page(page) -// .await -// .expect("could not retrieve posts"); - -// let flash = flash.map(FlashMessage::into_inner); - -// Template::render( -// "index", -// context! { -// posts: posts, -// flash: flash, -// page: page, -// num_pages: num_pages, -// }, -// ) -// } - -// #[get("/")] -// async fn edit(conn: Connection, id: i32) -> Template { -// let post: Option = Post::find_by_id(id) -// .one(&conn) -// .await -// .expect("could not find post"); - -// Template::render( -// "edit", -// context! { -// post: post, -// }, -// ) -// } - -// #[delete("/")] -// async fn delete(conn: Connection, id: i32) -> Flash { -// let post: post::ActiveModel = Post::find_by_id(id) -// .one(&conn) -// .await -// .unwrap() -// .unwrap() -// .into(); - -// post.delete(&conn).await.unwrap(); - -// Flash::success(Redirect::to("/"), "Post successfully deleted.") -// } - -// #[delete("/")] -// async fn destroy(conn: Connection) -> Result<()> { -// Post::delete_many().exec(&conn).await.unwrap(); -// Ok(()) -// } - -// #[catch(404)] -// pub fn not_found(req: &Request<'_>) -> Template { -// Template::render( -// "error/404", -// context! { -// uri: req.uri() -// }, -// ) -// } - -// async fn run_migrations(rocket: Rocket) -> fairing::Result { -// let db_url = Db::fetch(&rocket).unwrap().db_url.clone(); -// let conn = sea_orm::Database::connect(&db_url).await.unwrap(); -// let _ = setup::create_post_table(&conn).await; -// Ok(rocket) -// } - -// #[launch] -// fn rocket() -> _ { -// rocket::build() -// .attach(Db::init()) -// .attach(AdHoc::try_on_ignite("Migrations", run_migrations)) -// .mount("/", FileServer::from(relative!("/static"))) -// .mount( -// "/", -// routes![new, create, delete, destroy, list, edit, update], -// ) -// .register("/", catchers![not_found]) -// .attach(Template::fairing()) -// } + println!("Listening on: 127.0.0.1:8080"); + HttpServer::new(|| { + let tera = + Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap(); + App::new() + .data(tera) + .wrap(middleware::Logger::default()) // enable logger + .service(fs::Files::new("/static", "./static").show_files_listing()) + .service(web::resource("/").route(web::get().to(list))) + }) + .bind("127.0.0.1:8080")? + .run() + .await +} diff --git a/examples/actix_example/src/post.rs b/examples/actix_example/src/post.rs index 0bce0e7a..3f74d0ab 100644 --- a/examples/actix_example/src/post.rs +++ b/examples/actix_example/src/post.rs @@ -1,8 +1,8 @@ -use rocket::serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use sea_orm::entity::prelude::*; #[derive(Copy, Clone, Default, Debug, DeriveEntity, Deserialize, Serialize)] -#[serde(crate = "rocket::serde")] +#[serde(crate = "serde")] pub struct Entity; impl EntityName for Entity { @@ -12,9 +12,9 @@ impl EntityName for Entity { } #[derive( - Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Deserialize, Serialize, FromForm, + Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Deserialize, Serialize, )] -#[serde(crate = "rocket::serde")] +#[serde(crate = "serde")] pub struct Model { #[serde(skip_deserializing, skip_serializing_if = "Option::is_none")] pub id: Option, diff --git a/examples/actix_example/templates/base.html.tera b/examples/actix_example/templates/base.html.tera deleted file mode 100644 index 0b83d9ed..00000000 --- a/examples/actix_example/templates/base.html.tera +++ /dev/null @@ -1,81 +0,0 @@ - - - - - Rocket Todo Example - - - - - - - - - - - -
-

- - {# -
-

Rocket Todo

-
-
- - {% if msg %} - - {{ msg.1 }} - - {% endif %} -
-
- -
-
-
- -
-
-
    - {% for task in tasks %} {% if task.completed %} -
  • - {{ task.description }} -
    - - -
    -
    - - -
    -
  • - {% else %} -
  • - -
  • - {% endif %} {% endfor %} -
-
-
- #} {% block content %}{% endblock content %} -
- - diff --git a/examples/actix_example/templates/edit.html.tera b/examples/actix_example/templates/edit.html.tera deleted file mode 100644 index 47882e65..00000000 --- a/examples/actix_example/templates/edit.html.tera +++ /dev/null @@ -1,50 +0,0 @@ -{% extends "base" %} {% block content %} -
-

Edit Post

-
-
-
-
- - -
-
-
- - - -
-
-
- -
-
-
-
-
-
-
- - -
-
-
-
-
-{% endblock content %} diff --git a/examples/actix_example/templates/index.html.tera b/examples/actix_example/templates/index.html.tera index 0dc60fb9..d6ee0d13 100644 --- a/examples/actix_example/templates/index.html.tera +++ b/examples/actix_example/templates/index.html.tera @@ -1,46 +1,68 @@ -{% extends "base" %} {% block content %} -

Posts

-{% if flash %} - - {{ flash.1 }} - -{% endif %} - - - - - - - - - - {% for post in posts %} - - - - - - {% endfor %} - - - - - - - - -
IDTitleText
{{ post.id }}{{ post.title }}{{ post.text }}
- {% if page == 0 %} Previous {% else %} - Previous - {% endif %} | {% if page == num_pages - 1 %} Next {% else %} - Next - {% endif %} -
+ + + + + Actix Example + + + - + + + + + + + +
+

+

Posts

+ {# {% if flash %} + + {{ flash.1 }} + + {% endif %} #} + + + + + + + + + + {% for post in posts %} + + + + + + {% endfor %} + + + + + + + + +
IDTitleText
{{ post.id }}{{ post.title }}{{ post.text }}
+ {% if page == 0 %} Previous {% else %} + Previous + {% endif %} | {% if page == num_pages - 1 %} Next {% else %} + Next + {% endif %} +
-{% endblock content %} +
+ + + +
+
+ + diff --git a/examples/actix_example/templates/new.html.tera b/examples/actix_example/templates/new.html.tera deleted file mode 100644 index 57daffe2..00000000 --- a/examples/actix_example/templates/new.html.tera +++ /dev/null @@ -1,38 +0,0 @@ -{% extends "base" %} {% block content %} -
-

New Post

-
-
- - -
-
-
- - - -
-
-
- -
-
-
-
-{% endblock content %} diff --git a/examples/rocket_example/templates/base.html.tera b/examples/rocket_example/templates/base.html.tera index 0b83d9ed..4e45823e 100644 --- a/examples/rocket_example/templates/base.html.tera +++ b/examples/rocket_example/templates/base.html.tera @@ -2,9 +2,9 @@ - Rocket Todo Example - - + Rocket SeaORM Example + +

- - {# -
-

Rocket Todo

-
-
- - {% if msg %} - - {{ msg.1 }} - - {% endif %} -
-
- -
-
-
- -
-
-
    - {% for task in tasks %} {% if task.completed %} -
  • - {{ task.description }} -
    - - -
    -
    - - -
    -
  • - {% else %} -
  • - -
  • - {% endif %} {% endfor %} -
-
-
- #} {% block content %}{% endblock content %} + {% block content %}{% endblock content %}