Model Standards
Project-specific Django patterns for the World of Darkness application. These standards ensure consistency across gamelines.
Workflow Decision Tree
Creating a new polymorphic model?
→ See references/model-templates.md for Character/Item/Location inheritance patterns
Setting up CRUD views?
→ See references/view-templates.md for mixin order and permission patterns
Building forms?
→ See references/form-templates.md for ModelForm and formset patterns
Creating templates?
→ See references/template-patterns.md for inheritance and includes
Configuring URLs?
→ See references/url-patterns.md for namespace hierarchy
Checking what's implemented?
→ See references/model-inventory.md for full model status
Project-Specific Conventions
Model Type Registration
Every polymorphic model MUST set:
type = "model_name" # Snake_case, matches URL pattern
gameline = "gameline" # Lowercase: vampire, werewolf, mage, wraith, changeling, demon, mummy, hunter
URL Namespace Pattern
app:gameline:action:model_type
Example: characters:vampire:detail:vampire
Required Model Methods
def get_absolute_url(self):
return reverse("app:gameline:detail:model_type", kwargs={"pk": self.pk})
def get_update_url(self):
return reverse("app:gameline:update:model_type", kwargs={"pk": self.pk})
def get_heading(self):
return f"{self.gameline}_heading"
Gameline Heading Classes
| Gameline |
Class |
Color |
| Vampire |
vtm_heading |
Dark Red |
| Werewolf |
wta_heading |
Green |
| Mage |
mta_heading |
Purple |
| Wraith |
wto_heading |
Gray |
| Changeling |
ctd_heading |
Teal |
| Demon |
dtf_heading |
Dark Red |
| Mummy |
mtr_heading |
Gold |
| Hunter |
htr_heading |
Orange |
Mixin Stacking Order (left to right)
# Update views
class MyView(EditPermissionMixin, MessageMixin, UpdateView): pass
# List views
class MyListView(VisibilityFilterMixin, ListView): pass
# Create views
class MyCreateView(LoginRequiredMixin, MessageMixin, CreateView): pass
# ST-only views
class MySTView(STRequiredMixin, MessageMixin, CreateView): pass
Reference Model Inheritance
Do NOT redefine fields inherited from core.models.Model:
name, description, owner, chronicle, status, display
sources (M2M) - use add_source(book_title, page_number) method
File Location Patterns
| Component |
Path |
| Model |
app/models/gameline/model_name.py |
| Views |
app/views/gameline/{list,detail,create,update}.py |
| Forms |
app/forms/gameline/model_name.py |
| URLs |
app/urls/gameline/{list,detail,create,update}.py |
| Templates |
app/templates/app/gameline/model_name/{detail,list,form}.html |
| Display Includes |
app/templates/app/gameline/model_name/display_includes/ |
Implementation Checklist
Model Layer
URL Layer
View Layer
Form Layer
Template Layer
1---2name: model-standards3description: Code standards and templates for Django models, views, forms, templates, and URLs in this World of Darkness application. Use when creating new models (characters, items, locations), implementing reference/lookup models (factions, clans, disciplines), building CRUD views, designing forms, setting up URL patterns, or ensuring gameline consistency. Triggers on file creation/editing in characters/, items/, locations/ apps or when implementing polymorphic inheritance patterns.4---5
6# Model Standards
7
8Project-specific Django patterns for the World of Darkness application. These standards ensure consistency across gamelines.
9
10## Workflow Decision Tree
11
12**Creating a new polymorphic model?**
13→ See [references/model-templates.md](references/model-templates.md) for Character/Item/Location inheritance patterns
14
15**Setting up CRUD views?**
16→ See [references/view-templates.md](references/view-templates.md) for mixin order and permission patterns
17
18**Building forms?**
19→ See [references/form-templates.md](references/form-templates.md) for ModelForm and formset patterns
20
21**Creating templates?**
22→ See [references/template-patterns.md](references/template-patterns.md) for inheritance and includes
23
24**Configuring URLs?**
25→ See [references/url-patterns.md](references/url-patterns.md) for namespace hierarchy
26
27**Checking what's implemented?**
28→ See [references/model-inventory.md](references/model-inventory.md) for full model status
29
30## Project-Specific Conventions
31
32### Model Type Registration
33
34Every polymorphic model MUST set:
35```python
36type = "model_name" # Snake_case, matches URL pattern
37gameline = "gameline" # Lowercase: vampire, werewolf, mage, wraith, changeling, demon, mummy, hunter
38```
39
40### URL Namespace Pattern
41
42```
43app:gameline:action:model_type
44```
45Example: `characters:vampire:detail:vampire`
46
47### Required Model Methods
48
49```python
50def get_absolute_url(self):
51 return reverse("app:gameline:detail:model_type", kwargs={"pk": self.pk})
52
53def get_update_url(self):
54 return reverse("app:gameline:update:model_type", kwargs={"pk": self.pk})
55
56def get_heading(self):
57 return f"{self.gameline}_heading"
58```
59
60### Gameline Heading Classes
61
62| Gameline | Class | Color |
63|----------|-------|-------|
64| Vampire | `vtm_heading` | Dark Red |
65| Werewolf | `wta_heading` | Green |
66| Mage | `mta_heading` | Purple |
67| Wraith | `wto_heading` | Gray |
68| Changeling | `ctd_heading` | Teal |
69| Demon | `dtf_heading` | Dark Red |
70| Mummy | `mtr_heading` | Gold |
71| Hunter | `htr_heading` | Orange |
72
73### Mixin Stacking Order (left to right)
74
75```python
76# Update views
77class MyView(EditPermissionMixin, MessageMixin, UpdateView): pass
78
79# List views
80class MyListView(VisibilityFilterMixin, ListView): pass
81
82# Create views
83class MyCreateView(LoginRequiredMixin, MessageMixin, CreateView): pass
84
85# ST-only views
86class MySTView(STRequiredMixin, MessageMixin, CreateView): pass
87```
88
89### Reference Model Inheritance
90
91Do NOT redefine fields inherited from `core.models.Model`:
92- `name`, `description`, `owner`, `chronicle`, `status`, `display`
93- `sources` (M2M) - use `add_source(book_title, page_number)` method
94
95## File Location Patterns
96
97| Component | Path |
98|-----------|------|
99| Model | `app/models/gameline/model_name.py` |
100| Views | `app/views/gameline/{list,detail,create,update}.py` |
101| Forms | `app/forms/gameline/model_name.py` |
102| URLs | `app/urls/gameline/{list,detail,create,update}.py` |
103| Templates | `app/templates/app/gameline/model_name/{detail,list,form}.html` |
104| Display Includes | `app/templates/app/gameline/model_name/display_includes/` |
105
106## Implementation Checklist
107
108### Model Layer
109- [ ] Proper base class inheritance (Character/Human, ItemModel, LocationModel, or Model)
110- [ ] `type` and `gameline` attributes set
111- [ ] `__str__`, `get_absolute_url`, `get_update_url`, `get_heading` methods
112- [ ] Meta class with `verbose_name`, `verbose_name_plural`, `ordering`
113- [ ] Migration created and applied
114
115### URL Layer
116- [ ] List, detail, create, update URL patterns
117- [ ] Registered in gameline router
118- [ ] Names follow `app:gameline:action:model_name` convention
119
120### View Layer
121- [ ] Correct mixin stacking order
122- [ ] `select_related`/`prefetch_related` optimization
123- [ ] Form class selection based on permissions in UpdateView
124
125### Form Layer
126- [ ] Creation form with user-filtered querysets
127- [ ] Limited edit form for owners (non-ST users)
128
129### Template Layer
130- [ ] Extends appropriate base (`characters/core/human/detail.html`, etc.)
131- [ ] Uses `tg-card`, `tg-table` classes (not Bootstrap defaults)
132- [ ] Gameline heading class on cards