#filter #diesel #pagination #rocket #json

diesel_filter_query

针对Diesel过滤的过程宏

7个版本 (2个稳定版)

1.0.1 2023年11月6日
1.0.0 2022年9月14日
0.1.4 2022年1月12日
0.1.3 2021年11月10日
0.1.0 2021年8月13日

#1630 in 过程宏


diesel_filter中使用

MIT/Apache

17KB
298

Diesel Filter

Diesel Filter 是一种快速为您的Diesel模型添加过滤和分页的方法。适用于 DieselPostgres

包功能

  • rocket 在生成的过滤结构体上派生 FromForm查看示例
  • actix 在生成的过滤结构体上派生 Deserialize查看示例
  • pagination 添加了 Paginate 特性 (查看示例
  • serializepagination 添加了可以直接发送给客户端的 PaginatedPayload 特性

使用方法及示例

Cargo.toml

diesel_filter = { path = "../../diesel_filter/core", features = ["pagination", "serialize", "rocket"] }

使用 DieselFilter 派生您的结构体,并标注将用作过滤的字段。顶层注解 #[diesel(table_name = db_table)] 是必需的。

#[derive(Queryable, DieselFilter)]
#[diesel(table_name = projects)]
pub struct Project {
    pub id: Uuid,
    #[filter(substring, insensitive)]
    pub name: String,
    #[filter(substring)]
    pub owner_email: String,
    #[filter]
    pub owner_id: Uuid,
    pub created_at: NaiveDateTime,
}

#[filter] 注解可以接收要应用于它的过滤类型,目前只有 substringinsensitive

将生成一个用于过滤数据的结构体,其名称为 [YourStructName]Filters,例如:ProjectFilters。将生成两个方法(以下以 Project 为例)

pub fn filter<'a>(filters: &'a ProjectFilters) -> BoxedQuery<'a, Pg>

pub fn filtered(filters: &ProjectFilters, conn: &PgConnection) -> Result<Vec<Project>, Error>

可以使用 filter 方法与 inner_join 等其他 diesel 方法结合使用。

Project::filter(&filters)
    .inner_join(clients::table)
    .select((projects::id, clients::name))
    .load::<ProjectResponse>(conn)

使用 Rocket

使用 rocket 功能,可以从请求查询参数(点符号表示 ?filters.name=xxx)中获取生成的结构体。

use diesel_filter::PaginatedPayload;

#[get("/?<filters>")]
async fn index(filters: ClientFilters, conn: DbConn) -> Result<Json<PaginatedPayload<Client>>, Error> {
    Ok(Json(
        conn.run(move |conn| Client::filtered(&filters, conn))
            .await?
            .into(),
    ))
}

使用 Actix

使用 actix 功能,可以从请求查询参数中获取生成的结构体。

注意:与 rocket 集成不同,查询参数必须以未命名的方式发送。例如:?field=xxx&other=1

use diesel_filter::PaginatedPayload;

#[get("/")]
async fn index(filters: web::Query(ClientFilters), conn: DbConn) -> Result<Json<PaginatedPayload<Client>>, Error> {
    Ok(Json(
        conn.run(move |conn| Client::filtered(&filters, conn))
            .await?
            .into(),
    ))
}

使用分页

使用 pagination 功能,您可以使用 paginateper_pageload_and_count 等方法。

use diesel_filter::Paginate;

Project::filter(&filters)
    .inner_join(clients::table)
    .select((projects::id, clients::name))
    .paginate(filters.page)
    .per_page(filters.per_page)
    .load_and_count::<ProjectResponse>(conn)

这些方法与您可以在您的结构体上添加的 #[pagination] 注解无关,该注解可以将 pageper_page 添加到生成的过滤器结构体中,并更改 filtered 方法的签名。

#[derive(Queryable, DieselFilter)]
#[diesel(table_name = projects)]
#[pagination]
pub struct Project

要将其转换为 Json,使用功能标志 serialize,您可以使用 PaginatedPayload

pub struct PaginatedPayload<T> {
    data: Vec<T>,
    total: i64,
}
#[get("/?<filters>")]
async fn index(filters: ProjectFilters, conn: DbConn) -> Result<Json<PaginatedPayload<Project>>, Error> {
    Ok(Json(
        conn.run(move |conn| Project::filtered(&filters))
        .await
        .into(),
    ))
}

许可证

Diesel filter 的许可证为以下之一,由您选择

依赖项

约 1.5MB
约 35K SLoC