#[derive(Views)]
{
// Attributes available to this derive:
#[views]
#[view]
}
Expand description
Derives view types for different access modes from a model struct.
This procedural macro generates up to three specialized view types based on the annotated model:
{Model}Get: For read/retrieval operations{Model}Create: For creation operations{Model}Patch: For update/modification operations
§Generated Types
For a struct named User, the macro generates:
UserGetwith appropriateSerializederives (if serde enabled)UserCreatewith appropriateDeserializederives (if serde enabled)UserPatchwithDefaultandDeserializederives (if serde enabled)
Each generated type implements View<ViewMode{Get,Create,Patch}> for the original type,
allowing generic code to work with different view modes.
§Container Attributes
The #[views(...)] attribute on the struct itself accepts:
-
crate = "path": Override the path to themodel_viewscrate. Useful when re-exporting or when the crate is available under a different name.ⓘ#[derive(Views)] #[views(crate = "my_models::views")] struct User { /* ... */ } -
serdeorserde = true: Automatically deriveSerializefor Get views andDeserializefor Create and Patch views. Also addsdeny_unknown_fieldsand appropriate field-level serde attributes.ⓘ#[derive(Views)] #[views(serde)] struct User { /* ... */ }
§Field Attributes
Each field can be independently configured for each view mode using #[views(...)]:
§Get Mode (get = "policy")
Controls how the field appears in the {Model}Get type:
"required"(default): Field is always present with its view type"optional": Field is wrapped inOption<T>"forbidden": Field is excluded from the Get view
§Create Mode (create = "policy")
Controls how the field appears in the {Model}Create type:
"required"(default): Field must be provided during creation"optional": Field is wrapped inOption<T>, with serde’sdefaultandskip_serializing_ifattributes when serde is enabled"forbidden": Field is excluded from the Create view
§Patch Mode (patch = "policy")
Controls how the field appears in the {Model}Patch type:
"patch"(default): Field is wrapped inPatch<T>, allowing explicit ignore/update"optional": Field is wrapped inPatch<Option<T>>"forbidden": Field is excluded from the Patch view
§Examples
§Basic Usage
use model_views::Views;
#[derive(Views)]
struct Article {
// ID only appears in Get view (auto-generated, can't be set)
#[views(get = "required", create = "forbidden", patch = "forbidden")]
id: u64,
// Title is required everywhere
#[views(get = "required", create = "required", patch = "required")]
title: String,
// Published status can be patched
#[views(get = "required", create = "optional", patch = "required")]
published: bool,
}This generates:
ArticleGet { id: u64, title: String, published: bool }ArticleCreate { title: String, published: Option<bool> }ArticlePatch { title: Patch<String>, published: Patch<bool> }
§With Serde Support
#[derive(Views)]
#[views(serde)]
struct User {
#[views(get = "required", create = "forbidden", patch = "forbidden")]
id: u64,
#[views(get = "required", create = "required", patch = "required")]
name: String,
}The generated types will have appropriate Serialize/Deserialize derives.
§Generic Types
The macro supports generic parameters:
#[derive(Views)]
struct Container<T> {
#[views(get = "required", create = "required", patch = "required")]
value: T,
}§Panics
The macro will panic at compile time if:
- Applied to an enum or union (only structs with named fields are supported)
- An unknown policy value is used (e.g.,
get = "invalid") - The
crateattribute contains an invalid path
§Implementation Details
- View types only include fields that have at least one non-forbidden policy
- If all fields are forbidden for a view mode, that view type is still generated (as an empty struct)
- Generated types preserve the original struct’s visibility and generic parameters
- Non-
#[views(...)]attributes from the original struct are copied to generated types - When serde is enabled, optional create fields get
#[serde(default, skip_serializing_if = "Option::is_none")]