Usage Guide

Access Patterns

Direct Access

from django_app_parameter.models import Parameter

# Get parameter object and retrieve typed value
param = Parameter.objects.get(slug="BLOG_TITLE")
title = param.get()  # Returns str

param = Parameter.objects.get(slug="BIRTH_YEAR")
year = param.get()  # Returns int

param = Parameter.objects.get(slug="TAX_RATE")
rate = param.get()  # Returns Decimal

Pros: Full access to parameter object for modifications.

Parameter Object

param = Parameter.objects.get(slug="BLOG_TITLE")

print(param.name)         # "Blog Title"
print(param.slug)         # "BLOG_TITLE"
print(param.value_type)   # "STR"
print(param.is_global)    # True/False

value = param.get()       # Auto-converted

Type Usage

STR (String)

Parameter.objects.create(
    name="Site Title",
    value="My Site",
    value_type=TYPES.STR
)
title = app_parameter.SITE_TITLE  # "My Site"

INT (Integer)

Parameter.objects.create(
    name="Max Upload Size",
    value="5242880",
    value_type=TYPES.INT
)
max_size = app_parameter.MAX_UPLOAD_SIZE  # 5242880

FLT (Float)

Parameter.objects.create(
    name="PI Value",
    value="3.14159",
    value_type=TYPES.FLT
)
pi = app_parameter.PI_VALUE  # 3.14159

Warning: Use DCL for money.

DCL (Decimal)

from decimal import Decimal

Parameter.objects.create(
    name="Tax Rate",
    value="20.00",
    value_type=TYPES.DCL
)
tax_rate = app_parameter.TAX_RATE  # Decimal('20.00')

BOO (Boolean)

Parameter.objects.create(
    name="Maintenance Mode",
    value="false",
    value_type=TYPES.BOO
)
if app_parameter.MAINTENANCE_MODE:
    return HttpResponse("Under maintenance")

Values: "true"/"false", "1"/"0", "yes"/"no" (case-insensitive).

DATE (Date)

from datetime import date

Parameter.objects.create(
    name="Launch Date",
    value="2024-12-31",
    value_type=TYPES.DATE
)
launch = app_parameter.LAUNCH_DATE  # date(2024, 12, 31)

Format: YYYY-MM-DD (ISO 8601).

DATETIME (Date and Time)

from datetime import datetime

Parameter.objects.create(
    name="Event Start",
    value="2024-12-31T23:59:59",
    value_type=TYPES.DATETIME
)
event = app_parameter.EVENT_START  # datetime(2024, 12, 31, 23, 59, 59)

Format: ISO 8601 (YYYY-MM-DDTHH:MM:SS).

TIME (Time)

from datetime import time

Parameter.objects.create(
    name="Opening Time",
    value="09:00:00",
    value_type=TYPES.TIME
)
opening = app_parameter.OPENING_TIME  # time(9, 0, 0)

Format: HH:MM:SS.

DURATION (Timedelta)

from datetime import timedelta

Parameter.objects.create(
    name="Session Timeout",
    value="3600",  # seconds
    value_type=TYPES.DURATION
)
timeout = app_parameter.SESSION_TIMEOUT  # timedelta(seconds=3600)

Stored as seconds, returned as timedelta.

URL (Validated URL)

Parameter.objects.create(
    name="API Endpoint",
    value="https://api.example.com",
    value_type=TYPES.URL
)
api_url = app_parameter.API_ENDPOINT  # "https://api.example.com"

Validates URL format. Raises ValueError if invalid.

EMAIL (Validated Email)

Parameter.objects.create(
    name="Contact Email",
    value="contact@example.com",
    value_type=TYPES.EMAIL
)
email = app_parameter.CONTACT_EMAIL  # "contact@example.com"

Validates email format. Raises ValueError if invalid.

PERCENTAGE (0-100 Float)

Parameter.objects.create(
    name="Discount",
    value="15.5",
    value_type=TYPES.PERCENTAGE
)
discount = app_parameter.DISCOUNT  # 15.5

Validates 0-100 range. Raises ValueError if out of range.

LIST (Comma-separated)

Parameter.objects.create(
    name="Allowed Tags",
    value="python, django, web",
    value_type=TYPES.LIST
)
tags = app_parameter.ALLOWED_TAGS  # ["python", "django", "web"]

Splits by comma, strips whitespace.

DICT (JSON Dictionary)

Parameter.objects.create(
    name="API Settings",
    value='{"host": "api.example.com", "port": 443}',
    value_type=TYPES.DICT
)
settings = app_parameter.API_SETTINGS  # {"host": "api.example.com", "port": 443}

Must be valid JSON object. Raises ValueError if not dict.

JSN (Any JSON)

Parameter.objects.create(
    name="Feature Flags",
    value='["feature1", "feature2"]',
    value_type=TYPES.JSN
)
flags = app_parameter.FEATURE_FLAGS  # ["feature1", "feature2"]

Any valid JSON (dict, list, etc.).

PATH (File Path)

from pathlib import Path

Parameter.objects.create(
    name="Log Directory",
    value="/var/log/myapp",
    value_type=TYPES.PATH
)
log_dir = app_parameter.LOG_DIRECTORY  # Path("/var/log/myapp")

Returns pathlib.Path object.

Modifying Parameters

Using set()

param = Parameter.objects.get(slug="TAX_RATE")
param.set(Decimal("19.6"))  # Type-safe, validates, saves

Validators run automatically before saving.

Using auto_cast

When you have a string value (e.g., from user input) and want to convert it to the parameter’s native type:

param = Parameter.objects.get(slug="TAX_RATE")
param.set("19.6", auto_cast=True)  # Converts "19.6" to Decimal, validates, saves

param = Parameter.objects.get(slug="MAX_SIZE")
param.set("1024", auto_cast=True)  # Converts "1024" to int, validates, saves

param = Parameter.objects.get(slug="LAUNCH_DATE")
param.set("2024-12-31", auto_cast=True)  # Converts to date, validates, saves

This saves you from manually converting types before calling set().

In Admin

Changes take effect immediately. Validators run on save.

Validators

Adding Validators

param = Parameter.objects.get(slug="EMAIL")

# Add validator
param.validators.create(
    validator_type="EmailValidator",
    validator_params={}
)

# With parameters
param.validators.create(
    validator_type="MinValueValidator",
    validator_params={"limit_value": 0}
)

Built-in Validators

Value Validators:

  • MinValueValidator: {"limit_value": 0}

  • MaxValueValidator: {"limit_value": 100}

Length Validators:

  • MinLengthValidator: {"limit_value": 3}

  • MaxLengthValidator: {"limit_value": 255}

Pattern Validators:

  • RegexValidator: {"regex": "^[A-Z]+$"}

  • validate_slug: No params

Format Validators:

  • EmailValidator: No params

  • URLValidator: No params

  • validate_ipv4_address: No params

  • validate_ipv6_address: No params

File Validators:

  • FileExtensionValidator: {"allowed_extensions": ["pdf", "jpg"]}

Custom Validators

Define in settings:

# settings.py
DJANGO_APP_PARAMETER = {
    'validators': {
        'even_number': 'myapp.validators.validate_even_number',
        'french_phone': 'myapp.validators.validate_french_phone',
    }
}
# myapp/validators.py
from django.core.exceptions import ValidationError

def validate_even_number(value):
    if value % 2 != 0:
        raise ValidationError(f"{value} is not even")

Use:

param.validators.create(
    validator_type="even_number",
    validator_params={}
)

Validator JSON Format

For load_param command:

{
    "name": "Tax Rate",
    "value": "20.0",
    "value_type": "DCL",
    "validators": [
        {
            "validator_type": "MinValueValidator",
            "validator_params": {"limit_value": 0}
        },
        {
            "validator_type": "MaxValueValidator",
            "validator_params": {"limit_value": 100}
        }
    ]
}

See management-commands.md.

In Views

from django.shortcuts import render
from django_app_parameter import app_parameter
from datetime import date

def home(request):
    if app_parameter.MAINTENANCE_MODE:
        return HttpResponse("Under maintenance", status=503)

    launch_date = app_parameter.LAUNCH_DATE
    if date.today() < launch_date:
        return HttpResponse("Coming soon!")

    context = {
        'title': app_parameter.SITE_TITLE,
        'contact': app_parameter.CONTACT_EMAIL,
        'discount': app_parameter.DISCOUNT,
    }
    return render(request, 'home.html', context)

In Templates

Setup in settings.py:

TEMPLATES = [{
    'OPTIONS': {
        'context_processors': [
            'django_app_parameter.context_processors.add_global_parameter_context',
        ],
    },
}]

Usage:

<title>{{ SITE_TITLE }}</title>
<a href="mailto:{{ CONTACT_EMAIL }}">Contact</a>

{% if MAINTENANCE_MODE %}
    <div class="alert">Maintenance scheduled</div>
{% endif %}

Note: Only is_global=True parameters are available in templates. Parameters are passed in their declared format (int, bool, etc.).

Advanced Patterns

Caching

from django.core.cache import cache

def get_cached_param(slug, timeout=3600):
    key = f"param_{slug}"
    value = cache.get(key)
    if value is None:
        value = getattr(app_parameter, slug)
        cache.set(key, value, timeout)
    return value

Default Values

def get_param_or_default(slug, default):
    try:
        return getattr(app_parameter, slug)
    except ImproperlyConfigured:
        return default

Dynamic Feature Flags

def feature_enabled(feature_name):
    try:
        return getattr(app_parameter, f"ENABLE_{feature_name.upper()}")
    except ImproperlyConfigured:
        return False

Best Practices

  1. Use appropriate types: DATE for dates, DCL for money, PERCENTAGE for percentages

  2. Add validators: Ensure data integrity

  3. Cache frequently accessed params: Reduce DB queries

  4. Don’t store secrets: No encryption

  5. Use descriptive names: Help admins understand purpose

  6. Set is_global carefully: Only for template-needed params

  7. Document in description: Explain purpose and format

Next