У меня есть модель Django, в которой для каждого экземпляра требуется уникальный идентификатор, полученный из трех полей:
class Example(Model):
type = CharField(blank=False, null=False) # either 'A' or 'B'
timestamp = DateTimeField(default=timezone.now)
number = models.IntegerField(null=True) # a sequential number
. При этом создается метка вида [type][timestamp YEAR][number]
, которая должна быть уникальной, если только number
равно нулю.
Я подумал, что смогу использовать пару аннотаций:
uid_expr = Case(
When(
number=None,
then=Value(None),
),
default=Concat(
'type', ExtractYear('timestamp'), 'number',
output_field=models.CharField()
),
output_field=models.CharField()
)
uid_count_expr = Count('uid', distinct=True)
Я переопределил get_queryset
менеджера модели, чтобы применить аннотации по умолчанию, а затем попытался использовать CheckConstraint
:
class Example(Model):
...
class Meta:
constraints = [
models.CheckConstraint(check=Q(uid_cnt=1), name='unique_uid')
]
Это не удается, поскольку не удается найти поле в экземпляре с именем uid_cnt
, однако я думал, что аннотации были доступны для Q
объектов. Похоже, CheckConstraint
запрашивает модель напрямую, а не с использованием набора запросов, возвращаемого менеджером:
class CheckConstraint(BaseConstraint):
...
def _get_check_sql(self, model, schema_editor):
query = Query(model=model)
...
Есть ли способ применить ограничение к аннотации? Или есть лучший подход?
Я бы очень хотел применить это на уровне базы данных.
Спасибо.