Since the admin is an ASGI app, you can either run it standalone like in the demo, or integrate it with a larger ASGI app.


Piccolo can help you create a new ASGI app using piccolo asgi new.

For example, using Starlette routes:

import uvicorn
from movies.endpoints import HomeEndpoint
from movies.tables import Director, Movie
from starlette.routing import Mount, Route, Router

from piccolo_admin.endpoints import create_admin

# The `allowed_hosts` argument is required when running under HTTPS. It's
# used for additional CSRF defence.
admin = create_admin([Director, Movie], allowed_hosts=[""])

router = Router(
        Route(path="/", endpoint=HomeEndpoint),
        Mount(path="/admin/", app=admin),

if __name__ == "__main__":

FastAPI example

Here’s a complete example of a FastAPI app using Piccolo admin.

from fastapi import FastAPI
from fastapi.routing import Mount
from movies.tables import Director, Movie
from piccolo.engine import engine_finder

from piccolo_admin.endpoints import create_admin

app = FastAPI(
                tables=[Director, Movie],
                # Specify a different site name in the
                # admin UI (default Piccolo Admin):
                site_name="My Site Admin",
                # Required when running under HTTPS:
                # allowed_hosts=[""],

async def open_database_connection_pool():
    engine = engine_finder()
    await engine.start_connnection_pool()

async def close_database_connection_pool():
    engine = engine_finder()
    await engine.close_connnection_pool()

To run use:

uvicorn app:app --port 8000 --host

Now you can go to localhost:8000/admin and log in as an admin user (see Authentication for how to create users).


class piccolo_admin.endpoints.create_admin(tables: Sequence[Union[Type[Table], TableConfig]], forms: List[FormConfig] = [], auth_table: Optional[Type[BaseUser]] = None, session_table: Optional[Type[SessionsBase]] = None, session_expiry: timedelta = timedelta(hours=1), max_session_expiry: timedelta = timedelta(days=7), increase_expiry: Optional[timedelta] = timedelta(minutes=20), page_size: int = 15, read_only: bool = False, rate_limit_provider: Optional[RateLimitProvider] = None, production: bool = False, site_name: str = 'Piccolo Admin', default_language_code: str = 'auto', translations: Optional[List[Translation]] = None, auto_include_related: bool = True, allowed_hosts: Sequence[str] = [], debug: bool = False, sidebar_links: Dict[str, str] = {})[source]
  • tables – Each of the tables will be added to the admin.

  • forms – For each FormConfig specified, a form will automatically be rendered in the user interface, accessible via the sidebar.

  • auth_table – Either a BaseUser, or BaseUser subclass table, which is used for fetching users. Defaults to BaseUser if none if specified.

  • session_table – Either a SessionsBase, or SessionsBase subclass table, which is used for storing and querying session tokens. Defaults to SessionsBase if none if specified.

  • session_expiry – How long a session is valid for.

  • max_session_expiry – The maximum time a session is valid for, taking into account any refreshes using increase_expiry.

  • increase_expiry – If set, the session_expiry will be increased by this amount if it’s close to expiry.

  • page_size – The admin API paginates content - this sets the default number of results on each page.

  • read_only – If True, all non auth endpoints only respond to GET requests - the admin can still be viewed, and the data can be filtered. Useful for creating online demos.

  • rate_limit_provider – Rate limiting middleware is used to protect the login endpoint against brute force attack. If not set, an InMemoryLimitProvider will be configured with reasonable defaults.

  • production – If True, the admin will enforce stronger security - for example, the cookies used will be secure, meaning they are only sent over HTTPS.

  • site_name – Specify a different site name in the admin UI (default 'Piccolo Admin').

  • default_language_code – Specify the default language used in the admin UI. The value should be an IETF language tag, for example 'en' for English. To see available values see piccolo_admin/translations/ The UI will be automatically translated into this language. If a value of 'auto' is specified, then we check the user’s browser for the language they prefer, using the navigator.language JavaScript API.

  • translations

    Specify which translations are available. By default, we use every translation in piccolo_admin/translations/

    Here’s an example - if we know our users only speak English or Croatian, we can specify that only those translations are visible in the language selector in the UI:

    from import ENGLISH, CROATIAN
        tables=[TableA, TableB],
        translations=[ENGLISH, CROATIAN]

    You can also use this to provide your own translations, if there’s a language we don’t currently support (though please open a PR to add it!):

    from piccolo.translations.models import Translation
    from import ENGLISH
    MY_LANGUAGE = Translation(
        language_name='My Language',
            'Welcome': 'XXXXX',
        tables=[TableA, TableB],
        translations=[ENGLISH, MY_LANGUAGE]

  • auto_include_related – If a table has foreign keys to other tables, those tables will also be included in the admin by default, if not already specified. Otherwise the admin won’t work as expected.

  • allowed_hosts – This is used by the CSRFMiddleware as an additional layer of protection when the admin is run under HTTPS. It must be a sequence of strings, such as [''].

  • debug – If True, debug mode is enabled. Any unhandled exceptions will return a stack trace, rather than a generic 500 error. Don’t use this in production!

  • sidebar_links

    Custom links in the navigation sidebar. Example uses cases:

    • Providing a quick way to get to specific pages with pre-applied filters/sorting.

    • Linking to relative external websites.

    Here’s a full example:

    from piccolo_admin.endpoints import create_admin
        tables=[Movie, Director],
            "Top Movies": "/admin/#/movie?__order=-box_office",
            "Google": ""