Skip to content

Commit

Permalink
docs: update to new pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
kaplanelad committed Mar 5, 2024
1 parent d8ec80f commit d08ae1b
Showing 1 changed file with 42 additions and 83 deletions.
125 changes: 42 additions & 83 deletions docs-site/content/docs/the-app/pagination.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,20 @@ flair =[]
In many scenarios, when querying data and returning responses to users, pagination is crucial. In `Loco`, we provide a straightforward method to paginate your data and maintain a consistent pagination response schema for your API responses.

How to Use Pagination


```rust
use sea_orm::Condition;
use loco_rs::concern::pagination;

let notes_query = Entity::find();
let mut condition = Condition::all().add(Column::Title.like("%loco%"));
let pagination = pagination::PaginationFilter {
page_size: 10,
page: 5
use loco_rs::prelude::*;

let pagination_query = model::query::PaginationQuery {
page_size: 100,
page: 1,
};
let results = pagination::paginate(

let condition = model::query::dsl::condition().contains(notes::Column::Title, "loco");
let paginated_notes = model::query::exec::paginate(
&ctx.db,
notes_query,
Some(condition),
&params.pagination,
notes::Entity::find(),
Some(condition.build()),
&pagination_query,
)
.await?;
```
Expand All @@ -45,95 +42,57 @@ let results = pagination::paginate(
- Call the paginate function.


### Using Pagination in Controller
In most cases, you'll want to implement pagination in your REST API responses. Let's create a notes endpoint as an example.


###### Setting Up Pagination View
After creating getting the `paginated_notes` in the previous example, you can choose which fileds from the model you want to return and keep the same pagination response in all your different data responses.

Define the data you're returning to the user in Loco views. If you're not familiar with views, refer to the [documentation]((@/docs/the-app/views.md)) for more context.


Create a notes view file in `src/view/notes` with the following code:

```rust
use crate::models::_entities::notes;
use loco_rs::controller::views::pagination::PaginationResponseTrait;
use sea_orm::EntityTrait;
use loco_rs::{
controller::views::pagination::{Pager, PagerMeta},
prelude::model::query::PaginatedResponse,
};
use serde::{Deserialize, Serialize};

use crate::models::_entities::notes;

#[derive(Debug, Deserialize, Serialize)]
pub struct ListResponse {
id: i32,
title: Option<String>,
content: Option<String>,
}

impl PaginationResponseTrait for ListResponse {
type Model = crate::models::_entities::notes::Entity;
type ResponseType = Self;

fn list(models: Vec<<Self::Model as EntityTrait>::Model>) -> Vec<Self::ResponseType> {
models.into_iter().map(|a| Self::new(&a)).collect()
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct PaginationResponse {}

impl ListResponse {
#[must_use]
pub fn new(note: &notes::Model) -> Self {
impl From<notes::Model> for ListResponse {
fn from(note: notes::Model) -> Self {
Self {
id: note.id.clone(),
title: note.title.clone(),
content: note.content.clone(),
content: note.content,
}
}
}

```

- `ListResponse` defines the fields returned to the user.
- Implement `PaginationResponseTrait` for `ListResponse` and specify the related model, creating a list function to convert models into view responses.

###### Implementing Pagination View
Now, create a `list` function endpoint under the notes endpoint and define `ListQueryParams` as the query parameters:

```rust
use loco_rs::concern::pagination;
use axum::extract::Query;
use crate::{
models::_entities::notes::Entity,
};


#[derive(Debug, Deserialize)]
pub struct ListQueryParams {
pub title: Option<String>,
pub content: Option<String>,
#[serde(flatten)]
pub pagination: pagination::PaginationFilter,
}


pub async fn list(
State(ctx): State<AppContext>,
Query(params): Query<ListQueryParams>,
) -> Result<Json<Pager<Vec<ListResponse>>>> {
let notes_query = Entity::find();
let mut condition = Condition::all();// .add(Column::Title.like("%loco%"));

let notes: Pager<Vec<ListResponse>> =
pagination::view::<ListResponse, crate::models::_entities::notes::Entity>(
&ctx.db,
notes_query,
Some(params.into_query()),
&params.pagination,
)
.await?;

format::json(notes)
impl PaginationResponse {
#[must_use]
pub fn response(data: PaginatedResponse<notes::Model>) -> Pager<Vec<ListResponse>> {
Pager {
results: data
.rows
.into_iter()
.map(ListResponse::from)
.collect::<Vec<ListResponse>>(),
info: PagerMeta {
page: data.info.page,
page_size: data.info.page_size,
total_pages: data.info.total_pages,
},
}
}
}
```

- `ListQueryParams` defines the allowed query parameters for your REST API.
- The `title` and `content` parameters filter rows in the database.
- The `pagination` parameter specifies the pagination parameters for the query.


This outlines your controller implementation. Define the parameters you want to return in your REST API view, then specify the query parameters, and you'll have pagination for any entity in your application.

0 comments on commit d08ae1b

Please sign in to comment.