BaseResource

The class every resource inherits from. It is a Django View subclass with async dispatch, attribute-driven configuration and a long list of overridable hooks.

Mental model

A resource is a description of how a model maps to HTTP. You set attributes (what fields are exposed, what is filterable, who owns rows) and BaseResource turns that into endpoints.

model is not mandatory. For RPC-style endpoints (webhooks, OAuth callbacks, search, integrations) skip model and define routes with your own handlers. Those endpoints still benefit from auth, rate limit, security middleware, OpenAPI generation — they just don't get the default CRUD handlers.

Lifecycle

Each request runs through dispatch. The flow is:

Per-instance state

Class attributes that default to None (lists, dicts) are normalized to per-instance objects in __init__. You can safely mutate self.list_fields, self.queryset_filter, etc., without leaking state across requests.

Overriding handlers

Replace any of get, post, patch, delete for full control, or override the inner pieces (get_objs, get_obj, create_obj, update_obj, delete_obj) to keep the surrounding plumbing.

class ReportResource(BaseResource):
    model = Report

    async def get_objs(self, request):
        # custom list logic, still benefits from pagination + filters
        return await super().get_objs(request)

Throwing controlled errors

Raise HTTPException(status, detail) from anywhere. The ExceptionMiddleware turns it into a JSON error response.

from zeromcp.exception import HTTPException

if not user.is_admin:
    raise HTTPException(403, 'Admins only')

0-mcp by Stamatios Stamou Jr — github.com/ssjunior/0-mcp