3.4 KiB
3.4 KiB
qualifiers-model
Erstellt und erweitert Django Models für das qualifiers-Modul (UEFA Qualifikationsturniere).
Trigger
- Neue QNode, QMatch, QGame, QGrouping Models
- Model-Erweiterungen für Qualifiers
- "qualifiers model", "qnode", "qmatch", "qgame"
Kontext
Das qualifiers-Modul verwaltet UEFA-Qualifikationsturniere mit folgender Hierarchie:
- QPath → QTier → QNode (Turnier-Struktur)
- QNode → QGrouping → QPosition (Gruppenbildung)
- QNode → QMatch → QGame (Spielpaarungen)
Regeln
-
Immer db_index für ForeignKeys setzen wenn häufig gefiltert wird:
scenario = models.ForeignKey('scheduler.Scenario', on_delete=models.CASCADE, db_index=True) -
Meta-Klasse mit indexes und constraints:
class Meta: ordering = ['-tier__ypos', '-stage__xpos'] constraints = [ models.UniqueConstraint(fields=['name', 'scenario'], name='unique_qnode_name_scenario') ] indexes = [ models.Index(fields=['scenario', 'tier', 'stage'], name='qnode_scenario_tier_stage_idx'), ] -
related_name konsistent benennen:
- Plural für ForeignKey:
related_name='groupings' - Model-Name für M2M:
related_name='qnodes_seeded'
- Plural für ForeignKey:
-
State-Machine Pattern für QNode:
NODESTATE_CHOICES = ( (0, "none"), # Warten auf Vorgänger (1, "seeded"), # Teams zugeordnet (2, "grouping"), # Gruppen gebildet (3, "draw"), # Spiele ausgelost (4, "finalized"), # Alle Ergebnisse da ) -
GameMixin für QGame verwenden:
from scheduler.models import GameMixin class QGame(GameMixin): # Erbt: homeGoals, awayGoals, resultEntered, season qnode = models.ForeignKey(QNode, ...) -
Signals mit transaction.atomic():
@receiver(post_save, sender=QGame) def post_match_signal(sender, instance, created, **kwargs): with transaction.atomic(): # Signal-Logik
Beispiel: Neues Feld zu QNode
# qualifiers/models.py
class QNode(models.Model):
# Existierende Felder...
# Neues Feld
auto_advance = models.BooleanField(
default=False,
help_text="Automatisch zum nächsten State wechseln"
)
Beispiel: Neues Model
# qualifiers/models.py
class QNodeViolation(models.Model):
"""Speichert Constraint-Verletzungen für einen Node."""
node = models.ForeignKey(
QNode,
on_delete=models.CASCADE,
related_name='violations',
db_index=True
)
scenario = models.ForeignKey(
'scheduler.Scenario',
on_delete=models.CASCADE,
db_index=True
)
type = models.CharField(max_length=50) # 'country_clash', 'distance', etc.
message = models.TextField()
severity = models.IntegerField(default=1) # 1=Warning, 2=Error
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['node', 'scenario'], name='qnodeviolation_node_scen_idx'),
]
Migration erstellen
conda activate planner
python manage.py makemigrations qualifiers
python manage.py migrate qualifiers
Referenz-Dateien
- qualifiers/models.py - Alle Models
- docs/qualifiers/models/ - Dokumentation