Load Vocabularies
This guide explains how to load controlled vocabularies from the ZineCore2 specification into your database.
Prerequisites
- ✅ ZineCore2 server installed
- ✅ PostgreSQL database created and migrated
- ✅ Spec submodule initialized (git submodule update --init)
- ✅ Virtual environment activated
Understanding Vocabularies
ZineCore2 uses 8 controlled vocabularies:
| Vocabulary | Used By | File |
|---|---|---|
| Subjects | Zines | spec/vocabularies/generated/django/subjects.json |
| Genres | Zines | spec/vocabularies/generated/django/genres.json |
| Agent Kinds | Agents | spec/vocabularies/generated/django/agent-kinds.json |
| Agent Roles | Agents | spec/vocabularies/generated/django/agent-roles.json |
| Repository Kinds | Repositories | spec/vocabularies/generated/django/repository-kinds.json |
| Access Status | Holdings | spec/vocabularies/generated/django/access-status.json |
| Rights Status | Zines | spec/vocabularies/generated/django/rights-status.json |
| Formats | Zines | spec/vocabularies/generated/django/formats.json |
Location: All vocabulary fixtures are in spec/vocabularies/generated/django/
Load All Vocabularies
Step 1: Ensure Spec is Up to Date
cd /path/to/server
git submodule update --remote spec
This pulls the latest vocabulary definitions.
Step 2: Run Load Command
cd backend
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py load_vocabularies
Expected output:
Loading vocabularies from spec...
✓ Loaded 45 subjects
✓ Loaded 12 genres
✓ Loaded 3 agent kinds
✓ Loaded 8 agent roles
✓ Loaded 7 repository kinds
✓ Loaded 5 access status codes
✓ Loaded 6 rights statements
✓ Loaded 10 formats
Successfully loaded all vocabularies!
Step 3: Verify
Check that vocabularies were loaded:
# Via Django shell
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py shell
>>> from catalog.models import Subject, Genre
>>> Subject.objects.count()
45
>>> Genre.objects.count()
12
Or via API:
curl http://localhost:8000/api/vocabularies/subjects/ | jq '.count'
# Should return: 45
Load Individual Vocabulary
To load only a specific vocabulary:
Subjects
cd backend
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py loaddata ../spec/vocabularies/generated/django/subjects.json
Genres
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py loaddata ../spec/vocabularies/generated/django/genres.json
Agent Kinds
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py loaddata ../spec/vocabularies/generated/django/agent-kinds.json
Update Vocabularies
When vocabularies change in the spec:
Step 1: Pull Latest Spec
cd /path/to/server
git submodule update --remote spec
Step 2: Reload Vocabularies
cd backend
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py load_vocabularies
Behavior:
- Existing terms are updated if changed
- New terms are added
- Removed terms are deleted (if not referenced by any records)
Step 3: Verify Changes
# Check via API
curl http://localhost:8000/api/vocabularies/subjects/
# Or via Django shell
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py shell
>>> from catalog.models import Subject
>>> Subject.objects.filter(code='new-subject-code').first()
Manual Vocabulary Management
Add Custom Term
If you need a custom vocabulary term not in the spec:
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py shell
from catalog.models import Subject
# Create custom subject
Subject.objects.create(
code='local-custom-subject',
label='Local Custom Subject',
definition='Custom subject term for local use',
uri='https://example.org/subjects#local-custom-subject'
)
Warning: Custom terms may be overwritten if they conflict with spec updates.
Delete Unused Term
from catalog.models import Genre
# Delete genre (only if not referenced by any zines)
Genre.objects.filter(code='obsolete-genre').delete()
Note: Django will prevent deletion if the term is referenced by any records.
Vocabulary Fixture Format
Vocabulary fixtures use Django's JSON fixture format:
[
{
"model": "catalog.subject",
"fields": {
"code": "feminism",
"label": "Feminism",
"definition": "Social, political, and economic equality of the sexes.",
"uri": "https://zinecore.org/v2/subjects#feminism"
}
},
{
"model": "catalog.subject",
"fields": {
"code": "punk",
"label": "Punk",
"definition": "Punk subculture and music.",
"uri": "https://zinecore.org/v2/subjects#punk"
}
}
]
Fields:
- code — Unique identifier (used in API)
- label — Display name
- definition — Term definition
- uri — Full URI for the term
Troubleshooting
"No such file or directory: spec/vocabularies/..."
Cause: Spec submodule not initialized
Solution:
cd /path/to/server
git submodule update --init
"IntegrityError: duplicate key value violates unique constraint"
Cause: Vocabulary term already exists
Solution: The load_vocabularies command should handle this. If using loaddata directly, delete existing terms first:
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py shell
from catalog.models import Subject
Subject.objects.all().delete()
Then reload.
"Cannot delete vocabulary term: still referenced by records"
Cause: Vocabulary term is used by existing records
Solution:
- Find records using the term:
from catalog.models import Zine, Subject
subject = Subject.objects.get(code='obsolete-term')
zines_using_term = Zine.objects.filter(subject__contains=[subject.code])
print(f"Used by {zines_using_term.count()} zines")
- Update those records to use a different term
- Then delete the vocabulary term
"Command 'load_vocabularies' not found"
Cause: Management command not available
Solution: Ensure you're in the backend/ directory and using the correct settings module:
cd backend
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py load_vocabularies
Vocabulary Workflow
For Spec Maintainers
If you maintain the spec and need to update vocabularies:
Step 1: Edit canonical source
cd spec
# Edit spec/vocabularies/canonical/subjects.json
Step 2: Rebuild generated files
cd spec
node scripts/build-vocabularies.js
This regenerates all formats (CSV, SKOS, JSON-LD, Django fixtures).
Step 3: Commit changes
git add vocabularies/canonical/ vocabularies/generated/
git commit -m "Update subjects vocabulary"
git push
Step 4: Update server
cd ../server
git submodule update --remote spec
cd backend
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py load_vocabularies
For Server Operators
If you only operate a server and don't maintain the spec:
Step 1: Pull latest spec
cd /path/to/server
git pull
git submodule update --remote spec
Step 2: Reload vocabularies
cd backend
DJANGO_SETTINGS_MODULE=zinecore.settings.development \
../.venv/bin/python manage.py load_vocabularies
Production Considerations
Before Production Deployment
- Load vocabularies before loading any data
- Test thoroughly to ensure all required terms exist
- Backup database before updating vocabularies
Updating Vocabularies in Production
# Backup first
pg_dump -U zinecore2 -d zinecore2_prod > backup-$(date +%Y%m%d).sql
# Update spec
git submodule update --remote spec
# Reload vocabularies
cd backend
DJANGO_SETTINGS_MODULE=zinecore.settings.production \
.venv/bin/python manage.py load_vocabularies
# Verify
DJANGO_SETTINGS_MODULE=zinecore.settings.production \
.venv/bin/python manage.py shell
>>> from catalog.models import Subject
>>> Subject.objects.count()
Monitoring
After updating vocabularies, check:
- Record counts — Ensure no unexpected changes
- API responses — Test vocabulary endpoints
- Application logs — Check for errors
Best Practices
DO:
- ✅ Always update spec submodule before loading vocabularies
- ✅ Use load_vocabularies command (handles updates gracefully)
- ✅ Backup database before major vocabulary changes
- ✅ Test vocabulary updates in development first
- ✅ Document any custom vocabulary terms you add
DON'T:
- ❌ Manually edit vocabulary records in the database
- ❌ Delete vocabulary terms that might be referenced
- ❌ Skip vocabulary loading during initial setup
- ❌ Use inconsistent vocabulary codes across environments
Next Steps
- Database Migrations — Apply schema changes
- Bulk Import Data — Import zine records
- Architecture: Models — Understanding vocabulary models