Guide: custom overrides¶
The default output is realistic, but sometimes you need a specific field to hold specific values — a curated set of product names, a fixed status, a foreign key drawn from a particular queryset. Overrides let you pin only those fields and let the engine generate everything else.
Overrides are a Python-API feature (seed(..., overrides=...)).
Override shapes¶
| You pass | The engine does |
|---|---|
| a value | uses it as-is for every row |
| a callable | calls it per row for a fresh value |
a range |
samples an item from it |
| a list/tuple | samples an item from it |
a QuerySet (for an FK) |
uses it as a reuse pool, resolved once |
| a model instance / pk (for an FK) | points every row at it |
Example¶
import random
from shop.models import Book, Author
REAL_TITLES = ["The Pragmatic Programmer", "Clean Code", "Refactoring"]
seed(Book, count=50, overrides={
"title": lambda: random.choice(REAL_TITLES), # curated names
"price": range(5, 100), # sampled 5–99
"status": "published", # constant
"author": Author.objects.filter(active=True), # FK reuse pool
})
Everything not listed — slug, ISBN, dates, description, other FKs — is still generated and constraint-checked as usual.
Single model vs several¶
For a single target model, overrides is a {field_name: override} map (as
above). When you seed several models at once, key the overrides by model label:
seed(["shop.Book", "shop.Author"], count=20, overrides={
"shop.Book": {"status": "published"},
"shop.Author": {"is_active": True},
})
Overrides and uniqueness¶
Overrides on a unique column still go through the uniqueness tracker, so a
sampled/generated override won't produce duplicates. If your override pool is
smaller than count for a unique column, generation will exhaust — give it a
pool at least as large as the row count.