# Template Loaders

Flexible template loading system supporting multiple sources including filesystem directories, Python packages, dictionaries, and custom loading functions. Loaders can be combined and configured for complex template discovery patterns.

## Capabilities

### FileSystem Loader

Loads templates from filesystem directories with support for multiple search paths, encoding options, and symbolic link following.

```python { .api }
class FileSystemLoader:
    def __init__(self, searchpath, encoding='utf-8', followlinks=False):
        """
        Initialize filesystem loader.
        
        Parameters:
            searchpath: Directory path or list of directory paths to search
            encoding: Template file encoding (default: 'utf-8')
            followlinks: Follow symbolic links (default: False)
        """
```

Usage example:

```python
from jinja2 import Environment, FileSystemLoader

# Single directory
env = Environment(loader=FileSystemLoader('templates'))

# Multiple directories
env = Environment(loader=FileSystemLoader(['templates', 'shared_templates']))

# With custom encoding
env = Environment(loader=FileSystemLoader('templates', encoding='latin-1'))
```

### Package Loader

Loads templates from Python package directories, useful for distributing templates within Python packages and accessing templates from installed packages.

```python { .api }
class PackageLoader:
    def __init__(self, package_name, package_path='templates', encoding='utf-8'):
        """
        Initialize package loader.
        
        Parameters:
            package_name: Python package name (e.g., 'myapp' or 'myapp.subpackage')
            package_path: Path within package to template directory (default: 'templates')
            encoding: Template file encoding (default: 'utf-8')
        """
```

Usage example:

```python
from jinja2 import Environment, PackageLoader

# Load from myapp/templates/
env = Environment(loader=PackageLoader('myapp'))

# Load from myapp/email_templates/
env = Environment(loader=PackageLoader('myapp', 'email_templates'))

# Load from installed package
env = Environment(loader=PackageLoader('some_third_party_package'))
```

### Dictionary Loader

Loads templates from a Python dictionary, useful for templates stored in memory, databases, or other non-filesystem sources.

```python { .api }
class DictLoader:
    def __init__(self, mapping):
        """
        Initialize dictionary loader.
        
        Parameters:
            mapping: Dictionary mapping template names to template source strings
        """
```

Usage example:

```python
from jinja2 import Environment, DictLoader

templates = {
    'hello.html': '<h1>Hello {{ name }}!</h1>',
    'goodbye.html': '<h1>Goodbye {{ name }}!</h1>',
    'base.html': '''
        <!DOCTYPE html>
        <html>
        <head><title>{{ title }}</title></head>
        <body>{% block content %}{% endblock %}</body>
        </html>
    '''
}

env = Environment(loader=DictLoader(templates))
template = env.get_template('hello.html')
```

### Function Loader

Loads templates via a custom function, providing maximum flexibility for custom template sources and dynamic template generation.

```python { .api }
class FunctionLoader:
    def __init__(self, load_func):
        """
        Initialize function loader.
        
        Parameters:
            load_func: Function that takes template name and returns (source, filename, uptodate_func) tuple
                      Returns None if template doesn't exist
                      uptodate_func should return True if template is current, False if needs reloading
        """
```

Usage example:

```python
from jinja2 import Environment, FunctionLoader
import os

def load_template(name):
    # Custom loading logic - could load from database, API, etc.
    filepath = f'/custom/templates/{name}'
    if os.path.exists(filepath):
        with open(filepath, 'r') as f:
            source = f.read()
        # Return (source, filename, uptodate_function)
        return source, filepath, lambda: os.path.getmtime(filepath)
    return None

env = Environment(loader=FunctionLoader(load_template))
```

### Prefix Loader

Maps template name prefixes to different loaders, enabling organized template namespacing and modular template organization.

```python { .api }
class PrefixLoader:
    def __init__(self, mapping, delimiter='/'):
        """
        Initialize prefix loader.
        
        Parameters:
            mapping: Dictionary mapping prefixes to loader instances
            delimiter: Delimiter separating prefix from template name (default: '/')
        """
```

Usage example:

```python
from jinja2 import Environment, PrefixLoader, FileSystemLoader, PackageLoader

loader = PrefixLoader({
    'app': FileSystemLoader('app_templates'),
    'admin': FileSystemLoader('admin_templates'), 
    'email': PackageLoader('myapp', 'email_templates'),
    'shared': FileSystemLoader('shared_templates')
})

env = Environment(loader=loader)

# Load templates with prefixes
app_template = env.get_template('app/index.html')
admin_template = env.get_template('admin/dashboard.html')
email_template = env.get_template('email/welcome.html')
```

### Choice Loader

Tries multiple loaders in sequence until one successfully loads the template, useful for template fallback chains and migration scenarios.

```python { .api }
class ChoiceLoader:
    def __init__(self, loaders):
        """
        Initialize choice loader.
        
        Parameters:
            loaders: List of loader instances to try in order
        """
```

Usage example:

```python
from jinja2 import Environment, ChoiceLoader, FileSystemLoader, PackageLoader

# Try custom templates first, fall back to package defaults
loader = ChoiceLoader([
    FileSystemLoader('custom_templates'),
    FileSystemLoader('default_templates'),
    PackageLoader('myapp', 'fallback_templates')
])

env = Environment(loader=loader)

# Will use first loader that has the template
template = env.get_template('page.html')
```

### Module Loader

Loads precompiled templates from Python modules, providing maximum performance by skipping template compilation at runtime.

```python { .api }
class ModuleLoader:
    def __init__(self, path):
        """
        Initialize module loader.
        
        Parameters:
            path: Import path or list of import paths to search for compiled templates
        """
```

Usage example:

```python
from jinja2 import Environment, ModuleLoader

# Assumes templates were precompiled to compiled_templates module
env = Environment(loader=ModuleLoader('compiled_templates'))

# Can also specify multiple paths
env = Environment(loader=ModuleLoader(['compiled_templates', 'fallback_templates']))
```

### Base Loader

Abstract base class for implementing custom loaders with specific loading logic and caching behavior.

```python { .api }
class BaseLoader:
    def get_source(self, environment, template):
        """
        Get template source, filename, and update function.
        
        Parameters:
            environment: Jinja2 environment instance
            template: Template name to load
            
        Returns:
            tuple: (source, filename, uptodate_func) or raises TemplateNotFound
                   uptodate_func returns True if template is current
        """
    
    def list_templates(self):
        """
        List all available templates.
        
        Returns:
            list: List of template names (optional, may raise NotImplementedError)
        """
    
    def load(self, environment, name, globals=None):
        """
        Load and compile template.
        
        Parameters:
            environment: Jinja2 environment instance
            name: Template name
            globals: Additional globals for template
            
        Returns:
            Template: Compiled template instance
        """
```

## Utility Functions

```python { .api }
def split_template_path(template):
    """
    Split template path into directory and filename components.
    
    Parameters:
        template: Template path string
        
    Returns:
        list: Path components
        
    Raises:
        TemplateNotFound: If template path is invalid
    """
```

## Types

```python { .api }
class LoaderContext:
    """
    Context object passed to loader functions containing environment and template information.
    
    Attributes:
        environment: Jinja2 environment instance
        template: Template name being loaded
        filename: Template filename (if available)
    """
```