Using RestView#
AsyncRestView and
RestView define five CRUD endpoint
methods for one SQLAlchemy model. A subclass supplies the URL prefix, model,
and optional Pydantic schemas. include_view() registers the inherited endpoint methods
as FastAPI routes:
@fr.include_view(app)
class UserView(fr.AsyncRestView):
prefix = "/users"
model = User
UserView now serves list, create, retrieve, update, and delete requests under
/users. Getting Started supplies the surrounding app,
database configuration, and model in one runnable file.
Choose async or sync#
Use AsyncRestView for new
applications unless the application already uses synchronous SQLAlchemy. It
receives an AsyncSession through fr.AsyncSessionDep, and methods you
override are normally async def methods.
Use RestView with synchronous
SQLAlchemy sessions or sync-only libraries. It receives a Session through
fr.SessionDep. Both classes expose the same routes, configuration, and
override points. Mixed applications can choose per view.
Define the resource#
Every CRUD view needs two class attributes:
prefixis the URL prefix shared by every route in the view.modelis the SQLAlchemy mapped class that the routes read and write.
Ordinary models based on SQLAlchemy’s DeclarativeBase work. Restly’s
IDBase is an optional convenience base,
not a requirement.
If the view does not declare schema, Restly generates the view’s schema
from model when the view is registered. It then derives the create and update
schemas from it. Write the view’s schema yourself when the
wire contract needs stable field names, validation, aliases, or fields that do
not match the table directly:
class UserSchema(fr.IDSchema):
name: str
email: str
@fr.include_view(app)
class UserView(fr.AsyncRestView):
prefix = "/users"
model = User
schema = UserSchema
The four schema attributes have separate jobs:
Attribute |
Used for |
Default |
|---|---|---|
The source that Restly derives the other three from |
Constructed from |
|
|
|
|
|
|
|
|
Writable fields from |
Both derived schemas also leave out a primary key the server generates
(autoincrement, a column default, or a dataclass field with init=False),
marked ReadOnly or not. A natural key stays writable.
Custom Schemas and Field Types owns field markers, aliases, validation, and the choice between explicit and constructed schemas.
For larger applications, define the class without registration side effects and include it where the app or router is assembled:
class UserView(fr.AsyncRestView):
prefix = "/users"
model = User
schema = UserSchema
fr.include_view(app, UserView)
Both registration forms produce the same routes. Project structure shows where the direct call belongs in a multi-package application.
Default CRUD behavior#
For prefix = "/users", include_view registers the inherited endpoint
methods as this HTTP contract:
Request |
Endpoint method |
Input |
Response |
Status |
|---|---|---|---|---|
|
List query parameters |
Paginated |
|
|
|
|
|
|
|
|
Scalar path ID |
|
|
|
|
|
|
|
|
|
Scalar path ID |
Empty body |
|
The collection path without a trailing slash is canonical. Restly also accepts the trailing-slash form as a hidden compatibility route.
List filters are derived from fields shared by schema and model. Sorting
uses ?sort=field,-other_field. Pagination is on by default with a page size
of 50, a maximum accepted page size of 1000, and a response shaped like:
{
"data": [{"id": 1, "name": "Jane", "email": "jane@example.com"}],
"total_count": 1,
"page": 1,
"page_size": 50,
"total_pages": 1
}
Unknown list query keys return 422 instead of being ignored. Filter, Sort,
and Paginate Lists defines the complete query
grammar. Response Envelopes and List Metadata
defines the default containers and how to replace them.
Missing or hidden rows return 404. On the default endpoints, the create,
update, and delete handlers run authorization, call the business method, run
the commit hooks, and commit before the response is built. A custom endpoint
can group several handlers under one
shared_write_action_commit()
block. The outermost block then owns the commit and after-hooks. Reads do not
commit.
Important
Restly does not authenticate requests or impose an authorization policy.
authorize() permits every
action unless a subclass overrides it. Add authentication through FastAPI
dependencies, then enforce per-action policy in authorize() where needed.
Item paths and static routes#
The built-in GET, PATCH, and DELETE item paths follow
id_type. By default, it is
inferred from the model’s primary key. React Admin’s PUT uses the same path.
ID type |
Registered item path |
Matching values |
|---|---|---|
|
|
Non-negative digits, including |
|
|
UUIDs accepted by Starlette’s converter |
Any other type |
|
Any single path segment, then FastAPI validation |
An integer or UUID item route leaves /users/me available to a static route
registered after the view. A value that does not match the converter returns
404 instead of the previous 422, unless another route handles it. Negative
integer IDs do not match, even if the row exists. OpenAPI still shows
/users/{id} with the integer or UUID parameter schema.
Custom endpoint declarations keep their paths. To accept negative integer
IDs, replace each needed item endpoint with an untyped path such as
@fr.get("/{id}") and annotate its id parameter as int. See
Customizing RestView for endpoint replacements. Register
static routes before untyped item routes, including views with string IDs.
Configure a view#
Configure the class according to the contract the resource needs:
Requirement |
Configuration |
|---|---|
Stable response fields |
Declare |
Different create or update validation |
Declare |
A different type for the |
Set |
Read-only or otherwise restricted routes |
Set |
Disable pagination |
Set |
Change page limits, parameter names, or the list envelope |
Set |
Accept a view-specific list query key |
Declare it on the endpoint method or in a dependency, or add it to |
Apply FastAPI metadata or dependencies to every route |
Set |
Set a route name, summary, or operation ID |
Set |
Use another session dependency |
Override the |
Behavior and Configuration Reference lists the exact attribute types and method signatures. Use Restly in an Existing Project covers custom engines, session generators, and a per-view session dependency.
Change behavior#
A request passes through an endpoint method, a handler, and a business method. Change the layer that owns the behavior instead of rewriting the entire route:
Change |
Use |
|---|---|
Stamp or transform data during create or update |
Override the business method in Customizing RestView; a server-stamped field is a column default on the model |
Hide rows from every read |
Declare a scope: |
Permit or reject an action |
Override |
Run an atomic side effect or a post-commit action |
Override |
Commit several handlers or custom actions together |
Wrap them in shared_write_action_commit() |
Change status, headers, request parameters, or response model |
Replace the endpoint method |
Add a path that is not part of CRUD |
Add a method with |
Share behavior across resources |
|
Replace the list query grammar |
Customizing RestView owns the lifecycle diagrams, complete override decision table, and worked recipes.
Limits and alternatives#
The default CRUD contract has these boundaries:
Resource identity is one scalar primary key on the generated routes. The
{id}path parameter takes the key’s Python type, so a UUID or string key needs no configuration. A composite key is reached from a custom route that loads with a predicate (Look a row up by another key), or fromViewwith explicit route paths.Nested response schemas and relationship filtering are supported. General nested create and update payloads are not. Use
MustExist,IDRef, orIDSchemafor model-aware references, or transform the payload in a business method. See Work with Foreign Keys and Relationships.The default update route uses
PATCH, notPUT. Add an explicitPUTroute only when the client contract requires one.A
Viewgroups non-CRUD endpoints without adding CRUD methods. A plain FastAPI route remains the clearest choice for a single endpoint that shares no view configuration.
Next steps#
Getting Started builds and runs a first resource.
Customizing RestView changes behavior at the correct layer.
Custom Schemas and Field Types defines stable wire contracts.
Views explains registration, shared dependencies, and the inheritance model.
How-To Guides covers individual tasks.
Behavior and Configuration Reference lists exact signatures and defaults.