use sea_orm::{prelude::*, Condition, DatabaseConnection, EntityTrait, QueryFilter};
use serde::Deserialize;
#[allow(deprecated)]
use crate::{
controller::views::pagination::{Pager, PagerMeta, PaginationResponseTrait},
Result as LocoResult,
};
const fn default_page_size() -> u64 {
10
}
const fn default_page() -> u64 {
1
}
#[derive(Debug, Deserialize)]
pub struct PaginationFilter {
#[serde(
default = "default_page_size",
rename = "page_size",
deserialize_with = "deserialize_pagination_filter"
)]
pub page_size: u64,
#[serde(
default = "default_page",
rename = "page",
deserialize_with = "deserialize_pagination_filter"
)]
pub page: u64,
}
fn deserialize_pagination_filter<'de, D>(deserializer: D) -> Result<u64, D::Error>
where
D: serde::Deserializer<'de>,
{
let s: String = Deserialize::deserialize(deserializer)?;
s.parse().map_err(serde::de::Error::custom)
}
#[derive(Debug)]
pub struct PaginatedResponse<T> {
pub rows: Vec<T>,
pub page: u64,
pub page_size: u64,
pub total_pages: u64,
}
#[deprecated(
since = "0.3.2",
note = "reshape pagination functionality by moving under models. read more https://loco.rs/docs/the-app/pagination"
)]
pub async fn view<R, E>(
db: &DatabaseConnection,
entity: Select<E>,
filters: Option<Condition>,
pagination_filter: &PaginationFilter,
) -> LocoResult<Pager<Vec<<R as PaginationResponseTrait>::ResponseType>>>
where
E: EntityTrait,
<E as EntityTrait>::Model: Sync,
R: PaginationResponseTrait<Model = E>,
{
#![allow(deprecated)]
let res = paginate::<R, E>(db, entity, filters, pagination_filter).await?;
let res = Pager {
results: R::list(res.rows),
info: PagerMeta {
page: res.page,
page_size: res.page_size,
total_pages: res.total_pages,
},
};
Ok(res)
}
#[deprecated(
since = "0.3.2",
note = "reshape pagination functionality by moving under models. read more https://loco.rs/docs/the-app/pagination"
)]
pub async fn paginate<R, E>(
db: &DatabaseConnection,
entity: Select<E>,
filters: Option<Condition>,
pagination_filter: &PaginationFilter,
) -> LocoResult<PaginatedResponse<<E as EntityTrait>::Model>>
where
E: EntityTrait,
<E as EntityTrait>::Model: Sync,
R: PaginationResponseTrait<Model = E>,
{
#![allow(deprecated)]
let page = if pagination_filter.page <= 1 {
0
} else {
pagination_filter.page - 1
};
let entity = if let Some(filter) = filters {
entity.filter(filter)
} else {
entity
};
let query = entity.paginate(db, pagination_filter.page_size);
let page_count = query.num_pages().await?;
let rows: Vec<<E as EntityTrait>::Model> = query.fetch_page(page).await?;
let paginated_response = PaginatedResponse {
rows,
page: pagination_filter.page,
page_size: pagination_filter.page_size,
total_pages: page_count,
};
Ok(paginated_response)
}