"Right" way to define helper functions for Django models' Meta classes
I'm trying to simplify a very verbose and repetitive Check
constraint for a model, whose logic is currently very hard to parse, factoring out and aptly renaming the repetitive parts.
Basically I want to turn this (simplified and abstracted snippet):
class MyModel(models.Model):
class Meta:
constraints = [
models.CheckConstraint(
check = (
(
models.Q(foo = True)
& (
(
models.Q(field1 = 'X')
& models.Q(field2 = 'Y')
& models.Q(field3 = 'Z')
)
|
(
models.Q(field4 = 1)
& models.Q(field5 = 2)
& models.Q(field6 = 3)
)
)
)
|
(
models.Q(foo = False)
& (
(
models.Q(field1 = 'X')
& models.Q(field2 = 'Y')
& models.Q(field3 = 'Z')
)
|
(
models.Q(field4 = 4)
& models.Q(field5 = 5)
& models.Q(field6 = 6)
)
)
)
),
name = 'foo',
),
]
Into this:
class MyModel(models.Model):
class Meta:
constraints = [
models.CheckConstraint(
check = (
(
models.Q(foo = True)
& (
condition1
|
condition2
)
)
|
(
models.Q(foo = False)
& (
condition1
|
condition3
)
)
),
name = 'foo',
),
]
What I've tried / thought of trying:
- Factoring out the conditions, both as attributes and methods in Meta itself; that didn't work:
TypeError: 'class Meta' got invalid attribute(s): condition1,condition2,condition3
; - Factoring out the conditions, both as attributes and methods in MyModel; that of course wouldn't work, as you can't directly reference
MyModel
from insideMeta
; - Factoring out the conditions as attributes at
models.py
's root (hence outside of bothMeta
andMyModel
); that worked; however, this leaves the conditions loosely coupled withMyModel
and itsMeta
, which is undesirable in this case, as those conditions are strictly tied to both, and they're not meant to be reused anywhere anyways.
So even though the problem has been solved by simply putting the conditions somewhere else, I was wondering: is there an elegant way to do the same but preserving the strict coupling between the conditions and MyModel
or its Meta
class?