# Django Utilities

Utility functions and test runner integration for Django and pytest. This includes helper functions for Django configuration checks, test case identification, and the Django test runner class for manage.py integration.

## Capabilities

### Django Configuration Helpers

Utility functions for checking Django configuration state and skipping tests.

```python { .api }
def skip_if_no_django() -> None:
    """
    Skip test if Django settings are not configured.
    
    Raises pytest.skip if Django settings module is not available
    or Django is not properly configured. Used internally by fixtures
    to gracefully handle tests in non-Django environments.
    """

def django_settings_is_configured() -> bool:
    """
    Check if Django settings are configured.
    
    Checks both DJANGO_SETTINGS_MODULE environment variable and
    django.conf.settings.configured flag to determine if Django
    is properly set up.
    
    Returns:
        bool: True if Django settings are configured, False otherwise
    """

def get_django_version() -> tuple[int, int, int, str, int]:
    """
    Get Django version tuple.
    
    Returns Django version information in the same format as
    django.VERSION tuple.
    
    Returns:
        tuple: Django version as (major, minor, micro, releaselevel, serial)
    """
```

Usage examples:
```python
from pytest_django import skip_if_no_django, django_settings_is_configured

# Skip test if Django not available
def test_django_feature():
    skip_if_no_django()
    from django.contrib.auth.models import User
    # Test Django functionality

# Conditional test execution
def test_conditional_django():
    if not django_settings_is_configured():
        pytest.skip("Django not configured")
    # Test requires Django configuration
```

### Django Test Case Detection

Helper function for identifying Django test cases.

```python { .api }
def is_django_unittest(request_or_item: Union[pytest.FixtureRequest, pytest.Item]) -> bool:
    """
    Check if request or item is a Django test case.
    
    Determines whether a pytest request or item represents a Django
    unittest-style test case (subclass of django.test.SimpleTestCase).
    Used internally for applying Django-specific test setup.
    
    Args:
        request_or_item: pytest FixtureRequest or Item to check
        
    Returns:
        bool: True if item is Django test case, False otherwise
    """
```

Usage example:
```python
import pytest
from pytest_django import is_django_unittest

def pytest_runtest_setup(item):
    if is_django_unittest(item):
        # Apply Django-specific setup
        setup_django_test(item)
```

### Django Test Runner

Test runner class for using pytest with Django's manage.py test command.

```python { .api }
class TestRunner:
    """Django test runner that uses pytest for test discovery and execution."""
    
    def __init__(
        self,
        *,
        verbosity: int = 1,
        failfast: bool = False,
        keepdb: bool = False,
        **kwargs: Any
    ) -> None:
        """
        Initialize test runner with Django test command options.
        
        Args:
            verbosity: Test output verbosity level (0-3)
            failfast: Stop on first test failure
            keepdb: Preserve test database between runs
            kwargs: Additional keyword arguments
        """
    
    @classmethod
    def add_arguments(cls, parser: ArgumentParser) -> None:
        """
        Add command line arguments to Django test command parser.
        
        Adds pytest-django specific arguments to Django's test command,
        allowing integration with manage.py test.
        
        Args:
            parser: Django command argument parser
        """
    
    def run_tests(self, test_labels: Iterable[str], **kwargs: Any) -> int:
        """
        Run tests using pytest and return exit code.
        
        Translates Django test command options to pytest arguments
        and executes pytest with the specified test labels.
        
        Args:
            test_labels: Test labels to run (paths, modules, classes)
            kwargs: Additional keyword arguments
            
        Returns:
            int: pytest exit code (0 for success, non-zero for failures)
        """
```

Usage in Django settings:
```python
# settings.py
TEST_RUNNER = 'pytest_django.TestRunner'

# Now can use: python manage.py test
# Which will run pytest instead of Django's default test runner
```

Django management command usage:
```bash
# Run all tests with pytest
python manage.py test

# Run specific test with pytest
python manage.py test myapp.tests.test_models

# Run with pytest options via Django
python manage.py test --keepdb --failfast
```

## Utility Types

```python { .api }
from typing import Union, Iterable, Any, Tuple
from argparse import ArgumentParser
import pytest

# Django version type
DjangoVersion = Tuple[int, int, int, str, int]

# Test runner types
TestLabels = Iterable[str]
TestRunnerKwargs = dict[str, Any]
ExitCode = int

# Request/Item types
RequestOrItem = Union[pytest.FixtureRequest, pytest.Item]

# Test runner configuration
class TestRunnerConfig:
    verbosity: int
    failfast: bool
    keepdb: bool
    
# Argument parser type
CommandParser = ArgumentParser
```