| name | tg-character-templates |
| description | Character template system for World of Darkness character creation. Use when implementing template selection in character creation flows, creating/managing CharacterTemplate objects, adding template support to new character types, or working with the template import/export features. Triggers on character template work, pre-configured character concepts, template selection views. |
Character Template System
Pre-configured character concepts from sourcebooks that speed up character creation.
Overview
- 30 pre-configured templates (5 per gameline)
- Optional template selection during character creation
- Full customization after template application
- Usage tracking and admin management at
/admin/core/charactertemplate/
Template Data Structure
CharacterTemplate(
name="Template Name",
gameline="mta",
character_type="mage",
concept="Concept Name",
basic_info={"nature": "FK:Archetype:Name", "demeanor": "FK:Archetype:Name"},
attributes={"strength": 2, "perception": 4, ...},
abilities={"alertness": 2, "investigation": 3, ...},
backgrounds=[{"name": "Contacts", "rating": 3}],
powers={"auspex": 2, "celerity": 1},
merits_flaws=[{"name": "Merit Name", "rating": 2}],
specialties=["Ability (Specialty)"],
languages=["English", "Latin"],
is_official=True,
is_public=True,
times_used=0,
)
Note: Use "FK:Model:Name" format for foreign key references (resolved during apply).
Adding Template Selection to Character Types
Step 1: Add Form and View (in character views file)
from core.models import CharacterTemplate
from django import forms
class CharacterTemplateSelectionForm(forms.Form):
template = forms.ModelChoiceField(
queryset=CharacterTemplate.objects.none(),
required=False,
empty_label="No template - build from scratch",
widget=forms.RadioSelect,
)
def __init__(self, *args, gameline="vtm", character_type="vampire", **kwargs):
super().__init__(*args, **kwargs)
self.fields["template"].queryset = CharacterTemplate.objects.filter(
gameline=gameline, character_type=character_type, is_public=True
).order_by("name")
class VampireTemplateSelectView(LoginRequiredMixin, FormView):
form_class = CharacterTemplateSelectionForm
template_name = "characters/vampire/vampire/template_select.html"
def dispatch(self, request, *args, **kwargs):
self.object = get_object_or_404(Vampire, pk=kwargs["pk"], owner=request.user)
if self.object.creation_status > 0:
return redirect("characters:vampire:vampire_creation", pk=self.object.pk)
return super().dispatch(request, *args, **kwargs)
def get_form_kwargs():
kwargs = ().get_form_kwargs()
kwargs[] =
kwargs[] =
kwargs
():
template = form.cleaned_data.get()
template:
template.apply_to_character(.)
messages.success(.request, )
..creation_status =
..save()
redirect(, pk=..pk)
Step 2: Add URL
path("vampire/<int:pk>/template/", VampireTemplateSelectView.as_view(), name="vampire_template"),
Step 3: Update Basics View
def get_success_url(self):
return reverse("characters:vampire:vampire_template", kwargs={"pk": self.object.pk})
Step 4: Create Template Selection Template
{% extends "core/base.html" %}
{% block content %}
<div class="tg-card mb-4" data-gameline="vtm">
<div class="tg-card-header">
<h4 class="tg-card-title vtm_heading">Choose a Starting Template</h4>
</div>
<div class="tg-card-body">
<form method="post">
{% csrf_token %}
{% for template in available_templates %}
<div class="template-option" onclick="selectTemplate(this, {{ template.pk }})">
<h5>{{ template.name }}</h5>
<p>{{ template.description|truncatewords:30 }}</p>
</div>
{% endfor %}
<div class="template-option" onclick="selectTemplate(this, '')">
<h5>Build from Scratch</h5>
</div>
< = = = =>
Continue
{% endblock %}
Loading Templates
python populate_db/character_templates/__init__.py
python populate_db/character_templates/vampire_templates.py
Template Application Logic
CharacterTemplate.apply_to_character(character):
- Resolves
"FK:Model:Name" → actual objects
- Sets attributes and abilities directly
- Creates BackgroundRating entries
- Sets power ratings (disciplines/spheres/gifts)
- Creates MeritFlawRating entries
- Links Language objects
- Creates Specialty entries
- Creates TemplateApplication record
- Increments times_used counter
Reference Implementation
Mage (MtAHuman) is fully integrated. Files:
characters/views/mage/mtahuman.py - Template selection view
characters/urls/mage/detail.py - Template and creation URLs
characters/templates/characters/mage/mtahuman/template_select.html