def configure_app(config_path=None, project=None, default_config_path=None,
                  default_settings=None, settings_initializer=None,
                  settings_envvar=None, initializer=None, allow_extras=True,
                  config_module_name=None, runner_name=None, on_configure=None):
    """
    :param project: should represent the canonical name for the project, generally
        the same name it assigned in distutils.
    :param default_config_path: the default location for the configuration file.
    :param default_settings: default settings to load (think inheritence).
    :param settings_initializer: a callback function which should return a string
        representing the default settings template to generate.
    :param initializer: a callback function which will be executed before the command
        is executed. It is passed a dictionary of various configuration attributes.
    """
    global __configured

    project_filename = sanitize_name(project)

    if default_config_path is None:
        default_config_path = '~/%s/%s.conf.py' % (project_filename, project_filename)

    if settings_envvar is None:
        settings_envvar = project_filename.upper() + '_CONF'

    if config_module_name is None:
        config_module_name = project_filename + '_config'

    # normalize path
    if settings_envvar in os.environ:
        default_config_path = os.environ.get(settings_envvar)
    else:
        default_config_path = os.path.normpath(os.path.abspath(os.path.expanduser(default_config_path)))

    if not config_path:
        config_path = default_config_path

    config_path = os.path.expanduser(config_path)

    if not os.path.exists(config_path):
        if runner_name:
            raise ValueError("Configuration file does not exist. Use '%s init' to initialize the file." % (runner_name,))
        raise ValueError("Configuration file does not exist at %r" % (config_path,))

    os.environ['DJANGO_SETTINGS_MODULE'] = config_module_name

    def settings_callback(settings):
        if initializer is None:
            return

        try:
            initializer({
                'project': project,
                'config_path': config_path,
                'settings': settings,
            })
        except Exception:
            # XXX: Django doesn't like various errors in this path
            import sys
            import traceback
            traceback.print_exc()
            sys.exit(1)

    importer.install(
        config_module_name, config_path, default_settings,
        allow_extras=allow_extras, callback=settings_callback)

    __configured = True

    # HACK(dcramer): we need to force access of django.conf.settings to
    # ensure we don't hit any import-driven recursive behavior
    from django.conf import settings
    hasattr(settings, 'INSTALLED_APPS')

    if on_configure:
        on_configure({
            'project': project,
            'config_path': config_path,
            'settings': settings,
        })