python / expert
Snippet
Selektive Modell-Feld-Mutationsverfolgung über Dunder-Deskriptor-Mechanik
Pythons Deskriptor-Protokoll (`__get__` und `__set__`) ermöglicht eine feingliedrige Kontrolle über den Zugriff auf Modellfelder. Durch das Abfangen von Set-Operationen können Deskriptoren neue Werte mit internen Attributen vergleichen, um automatisch ein Tracking-Set für geänderte Felder auf Modellinstanzen zu befüllen.
snippet.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class TrackedFieldDescriptor:def __init__(self, field_name):self.field_name = field_nameself.internal_name = f"_{field_name}"def __get__(self, instance, owner=None):if instance is None:return selfreturn getattr(instance, self.internal_name, None)def __set__(self, instance, value):old_val = getattr(instance, self.internal_name, None)if old_val != value:dirty = getattr(instance, '_dirty_fields', set())dirty.add(self.field_name)setattr(instance, '_dirty_fields', dirty)setattr(instance, self.internal_name, value)
django
Erklärung
1
class TrackedFieldDescriptor:
Definiert eine benutzerdefinierte Python-Deskriptor-Klasse zur Verwaltung von Attributzugriffen.
2
def __init__(self, field_name):
Initialisiert den Deskriptor und speichert den Ziel-Feldnamen sowie den privaten Attribut-Schlüssel.
3
def __get__(self, instance, owner=None):
Verwaltet den Attributabruf für Instanz-Lookups oder den Zugriff auf Klassenebene.
4
if instance is None: return self
Gibt die Deskriptor-Instanz zurück, wenn über das Klassenobjekt anstelle der Modellinstanz zugegriffen wird.
5
def __set__(self, instance, value):
Fängt Zuweisungsoperationen für Modellattribute ab.
6
if old_val != value:
Vergleicht den neuen Wert mit dem vorhandenen privaten Wert, um Mutationen zu erkennen.
7
dirty = getattr(instance, '_dirty_fields', set())
Ruft das Set zur Verfolgung geänderter Feldnamen ab oder initialisiert es.
8
dirty.add(self.field_name)
Fügt den Feldnamen beim Auftreten einer Mutation zum Dirty-Set hinzu.
9
setattr(instance, '_dirty_fields', dirty)
Speichert das aktualisierte Dirty-Set wieder auf der Zielinstanz.
10
setattr(instance, self.internal_name, value)
Aktualisiert das private Instanz-Feldattribut mit dem neuen Wert.