Skip to content

App Registry

buraq.apps provides application configuration classes and a global registry — the same pattern as Django’s AppConfig.

buraq startapp writes an apps.py for you, with an empty ready() to fill in. It is optional — an app listed by its own name works without one — and this is what it looks like filled in:

blog/apps.py
from buraq.apps import AppConfig
class BlogConfig(AppConfig):
name = "blog"
verbose_name = "Blog"
async def ready(self):
import blog.signals # connect signals on startup

Register it in INSTALLED_APPS:

INSTALLED_APPS = [
"blog.apps.BlogConfig",
"shop", # plain package path also accepted
]

Both forms behave the same. Given a package, Buraq imports shop/apps.py and uses the AppConfig declared there; given a class path, it uses that class directly. If an apps.py declares more than one config, mark the one to use:

class ShopConfig(AppConfig):
name = "shop"
default = True
Attribute Description
name Dotted Python path to the app module
verbose_name Human-readable name (auto-generated from label if not set)
label Short name used as dict key (defaults to last part of name)
default Selects this config when the app’s apps.py declares several

ready() runs once during startup, after every installed app’s models module has been imported, so the ORM registry is fully populated by the time it is called. Use it to connect signals, register checks, or perform one-time initialization:

It only runs for an app registered by its config path, or one whose apps.py declares a config — an app listed as a bare package with no apps.py has no ready() to run.

async def ready(self):
from buraq.checks import register, Warning
@register
def check_stripe_key(settings, **kwargs):
if not getattr(settings, "STRIPE_SECRET_KEY", None):
return [Warning("STRIPE_SECRET_KEY is not set.", id="payments.W001")]
return []

Buraq loads INSTALLED_APPS for you — on ASGI startup and before any management command that sends a signal. You do not need to call populate() or run_ready_hooks() yourself; both are idempotent, so calling them again is harmless but does nothing.

from buraq.apps import apps
config = apps.get_app_config("blog")
config.verbose_name # "Blog"
apps.is_installed("blog") # True
apps.get_app_configs() # [BlogConfig, ...]
apps.ready # True once apps are loaded

configure() loads the settings module and imports every installed app’s models from a synchronous entry point. It is what a migration run calls, and it suits any standalone script that needs the ORM without starting the server:

from buraq.apps import configure
configure() # or configure("config.prod_settings")

It deliberately does not run ready() hooks — those are coroutines, and schema work does not need them. Inside the running application, startup already handles everything.

To run your own code around startup, register it:

app = Buraq(settings_module="config.settings")
@app.on_startup
async def warm_caches():
await load_feature_flags()
@app.on_shutdown
async def flush():
await metrics.flush()

Startup hooks run after the framework has loaded apps, run system checks and warmed the template and translation caches. Shutdown hooks run in reverse registration order, before the database engine is disposed, so they can still issue queries.