By leveraging Piccolo apps you can:
Modularise your code.
Share your apps with other Piccolo users.
Unlock some useful functionality like auto migrations.
Creating an app¶
Run the following command within your project:
piccolo app new my_app
my_app is your new app’s name. This will create a folder like this:
my_app/ __init__.py piccolo_app.py piccolo_migrations/ __init__.py tables.py
It’s important to register your new app with the
# piccolo_conf.py APP_REGISTRY = AppRegistry(apps=['my_app.piccolo_app'])
Anytime you invoke the
piccolo command, you will now be able to perform
operations on your app, such as Migrations.
Inside your app’s
piccolo_app.py file is an
AppConfig instance. This is
how you customise your app’s settings.
# piccolo_app.py import os from piccolo.conf.apps import AppConfig from .tables import ( Author, Post, Category, CategoryToPost, ) CURRENT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) APP_CONFIG = AppConfig( app_name='blog', migrations_folder_path=os.path.join( CURRENT_DIRECTORY, 'piccolo_migrations' ), table_classes=[Author, Post, Category, CategoryToPost], migration_dependencies=, commands= )
This is used to identify your app, when using the
piccolo CLI, for example:
piccolo migrations forwards blog
Specifies where your app’s migrations are stored. By default, a folder called
piccolo_migrations is used.
Use this to register your app’s
Table subclasses. This is important for
You can register them manually (see the example above), or can use table_finder.
Used to specify other Piccolo apps whose migrations need to be run before the current app’s migrations.
You can register functions and coroutines, which are automatically added to
The targ library is used under the hood. It makes it really easy to write command lines tools - just use type annotations and docstrings. Here’s an example:
def say_hello(name: str): """ Say hello. :param name: The person to greet. """ print("hello,", name)
We then register it with the
# piccolo_app.py APP_CONFIG = AppConfig( # ... commands=[say_hello] )
And from the command line:
>>> piccolo my_app say_hello bob hello, bob
If the code contains an error to see more details in the output add a
flag to the command line.
>>> piccolo my_app say_hello bob --trace
By convention, store the command definitions in a
commands folder in your
my_app/ __init__.py piccolo_app.py commands/ __init__.py say_hello.py
Piccolo itself is bundled with several apps - have a look at the source code for inspiration.
Instead of manually registering
Table subclasses, you can use
table_finder to automatically import any
Table subclasses from a given
list of modules.
from piccolo.conf.apps import table_finder APP_CONFIG = AppConfig( app_name='blog', migrations_folder_path=os.path.join( CURRENT_DIRECTORY, 'piccolo_migrations' ), table_classes=table_finder(modules=['blog.tables']), migration_dependencies=, commands= )
The module path should be from the root of the project (the same directory as
piccolo_conf.py file, rather than a relative path).
You can filter the
Table subclasses returned using tags.
- piccolo.conf.apps.table_finder(modules: Sequence[str], include_tags: Optional[Sequence[str]] = None, exclude_tags: Optional[Sequence[str]] = None, exclude_imported: bool = False) List[Type[Table]] ¶
Rather than explicitly importing and registering table classes with the
table_findercan be used instead. It imports any
Tablesubclasses in the given modules. Tags can be used to limit which
Tablesubclasses are imported.
modules – The module paths to check for
Tablesubclasses. For example,
['blog.tables']. The path should be from the root of your project, not a relative path.
include_tags – If the
Tablesubclass has one of these tags, it will be imported. The special tag
'__all__'will import all
exclude_tags – If the
Tablesubclass has any of these tags, it won’t be imported.
Tablesubclasses defined within the module are used. Any
Tablesubclasses imported by that module from other modules are ignored. For example:
from piccolo.table import Table from piccolo.column import Varchar, ForeignKey from piccolo.apps.user.tables import BaseUser # excluded class Task(Table): # included title = Varchar() creator = ForeignKey(BaseUser)