BaseUser is a Table you can use to store and authenticate your users.

Creating the Table

Run the migrations:

piccolo migrations forwards user


The app comes with some useful commands.


Creates a new user. It presents an interactive prompt, asking for the username, password etc.

piccolo user create

If you’d prefer to create a user without the interactive prompt (perhaps in a script), you can pass all of the arguments in as follows:

piccolo user create --username=bob --password=bob123  --is_admin=t --is_superuser=t --is_active=t


If you choose this approach then be careful, as the password will be in the shell’s history.


List existing users.


Change a user’s password.

piccolo user change_password


Change a user’s permissions. The options are --admin, --superuser and --active, which change the corresponding attributes on BaseUser.

For example:

piccolo user change_permissions some_user --active=true

The Piccolo Admin uses these attributes to control who can login and what they can do.

  • active and admin - must be true for a user to be able to login.

  • superuser - must be true for a user to be able to change other user’s passwords.

Within your code

create_user / create_user_sync

To create a new user:

# From within a coroutine:
await BaseUser.create_user(username="bob", password="abc123", active=True)

# When not in an event loop:
BaseUser.create_user_sync(username="bob", password="abc123", active=True)

It saves the user in the database, and returns the created BaseUser instance.


It is preferable to use this rather than instantiating and saving BaseUser directly, as we add additional validation.

login / login_sync

To check a user’s credentials, do the following:

from piccolo.apps.user.tables import BaseUser

# From within a coroutine:
>>> await BaseUser.login(username="bob", password="abc123")

# When not in an event loop:
>>> BaseUser.login_sync(username="bob", password="abc123")

If the login is successful, the user’s id is returned, otherwise None is returned.

update_password / update_password_sync

To change a user’s password:

# From within a coroutine:
await BaseUser.update_password(username="bob", password="abc123")

# When not in an event loop:
BaseUser.update_password_sync(username="bob", password="abc123")


Don’t use bulk updates for passwords - use update_password / update_password_sync, and they’ll correctly hash the password.


The maximum password length allowed is 128 characters. This should be sufficiently long for most use cases.

Extending BaseUser

If you want to extend BaseUser with additional fields, we recommend creating a Profile table with a ForeignKey to BaseUser, which can include any custom fields.

from piccolo.apps.user.tables import BaseUser
from piccolo.columns import ForeignKey, Text, Varchar
from piccolo.table import Table

class Profile(Table):
    custom_user = ForeignKey(BaseUser)
    phone_number = Varchar()
    bio = Text()

Alternatively, you can copy the entire user app into your project, and customise it to fit your needs.


class piccolo.apps.user.tables.BaseUser(**kwargs)

Provides a basic user, with authentication support.

async classmethod create_user(username: str, password: str, **extra_params) BaseUser

Creates a new user, and saves it in the database. It is recommended to use this rather than instantiating and saving BaseUser directly, as we add extra validation.


ValueError – If the username or password is invalid.


The created BaseUser instance.

classmethod create_user_sync(username: str, password: str, **extra_params) BaseUser

A sync equivalent of create_user().

async classmethod login(username: str, password: str) Optional[int]

Make sure the user exists and the password is valid. If so, the last_login value is updated in the database.


The id of the user if a match is found, otherwise None.

classmethod login_sync(username: str, password: str) Optional[int]

A sync equivalent of login().

async classmethod update_password(user: Union[str, int], password: str)

The password is the raw password string e.g. 'password123'. The user can be a user ID, or a username.

classmethod update_password_sync(user: Union[str, int], password: str)

A sync equivalent of update_password().