add paginator sample

This commit is contained in:
Manuel Gugger 2022-01-03 19:31:34 +01:00
parent 12796fecfe
commit 10c50d7ddb
10 changed files with 68 additions and 12 deletions

3
.env
View File

@ -1 +1,4 @@
DATABASE_URL=sqlite://database.db
OAUTH2_CLIENT_SECRET=
OAUTH2_CLIENT_ID=
OAUTH2_SERVER=

3
.gitignore vendored
View File

@ -13,3 +13,6 @@ Cargo.lock
# Added by cargo
/target
database.db
database.*
database.db-wal

View File

@ -23,5 +23,5 @@ serde = "1.0.130"
serde_json = "1.0.71"
serde_derive = "1.0.130"
sea-orm = { version = "^0", features = [ "sqlx-sqlite", "runtime-actix-native-tls", "macros" ], default-features = false }
sea-orm = { version = "0.5.0", features = [ "sqlx-sqlite", "runtime-actix-native-tls", "macros" ], default-features = false }

Binary file not shown.

Binary file not shown.

View File

@ -1,22 +1,65 @@
use actix_web::{web, guard, HttpRequest, HttpResponse};
use actix_web::{web, guard, HttpRequest, HttpResponse, Error, error};
use tera::{ Tera, Context};
use crate::entity::Post;
use crate::entity::post;
use sea_orm::{ entity::*, query::*, SelectorTrait, ModelTrait, ConnectionTrait, ColumnTrait, PaginatorTrait, EntityTrait };
use sea_orm::{{ DatabaseConnection, ConnectOptions }};
const DEFAULT_POSTS_PER_PAGE: usize = 5;
#[derive(Debug, Deserialize)]
pub struct Params {
page: Option<usize>,
posts_per_page: Option<usize>,
}
async fn index(data: web::Data<super::AppState>) -> &'static str {
"Welcome!"
}
async fn list(data: web::Data<super::AppState>) -> &'static str {
"List!"
async fn list<T: EntityTrait>(
req: HttpRequest,
data: web::Data<super::AppState>) -> Result<HttpResponse, Error>
{
let db = &data.db;
let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
let page = params.page.unwrap_or(1);
let posts_per_page = params.posts_per_page.unwrap_or(DEFAULT_POSTS_PER_PAGE);
let paginator = Post::find()
.order_by_asc(post::Column::Id)
.paginate(db, posts_per_page);
let num_pages = paginator.num_pages().await.ok().unwrap();
let posts = paginator
.fetch_page(page - 1)
.await
.expect("could not retrieve posts");
let mut ctx = Context::new();
ctx.insert("posts", &posts);
ctx.insert("page", &page);
ctx.insert("posts_per_page", &posts_per_page);
ctx.insert("num_pages", &num_pages);
let body = data.tmpl
.render("list.html", &ctx)
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::Ok().content_type("text/html").body(body))
}
fn entity_scope() -> actix_web::Scope {
let scope = web::scope("/entity")
.route("/list", web::get().to(list));
fn entity_scope<T: EntityTrait>(entity: T) -> actix_web::Scope {
let entity_name = entity.table_name();
let scope = web::scope(&format!("/{}",entity_name))
.route("/list", web::get().to(list::<T>));
scope
}
pub fn admin_scope() -> actix_web::Scope {
let scope = web::scope("/admin")
.route("/", web::get().to(index))
.service(entity_scope());
.service(entity_scope(Post));
scope
}

View File

@ -2,7 +2,7 @@
use sea_orm::sea_query::{ColumnDef, TableCreateStatement};
use sea_orm::{error::*, sea_query, ConnectionTrait, DbConn, ExecResult};
mod post;
pub mod post;
pub use post::Entity as Post;
// setup

View File

@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "posts")]
#[sea_orm(table_name = "post")]
pub struct Model {
#[sea_orm(primary_key)]
#[serde(skip_deserializing)]

View File

@ -74,7 +74,6 @@ async fn main() {
concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")
).unwrap();
dotenv::dotenv().ok();
let db_url = env::var("DATABASE_URL").expect("DATABASE_URL is not set in .env file");
let mut opt = ConnectOptions::new(db_url);
opt.max_connections(100)

8
templates/list.html Normal file
View File

@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block content %}
<p>posts: {{ posts }}</p>
<p>page: {{ page }}</p>
<p>posts_per_page: {{ posts_per_page }}</p>
<p>num_pages: {{ num_pages }}</p>
{% endblock content %}