Tengo un modelo de Django donde cada instancia requiere un identificador único que se deriva de tres campos:
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 Esto produce una etiqueta de la forma [type][timestamp YEAR][number] , que debe ser única a menos que number sea nulo.
Pensé que podría usar un par de anotaciones:
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) Anulé el get_queryset del administrador del modelo para aplicar las anotaciones de forma predeterminada y luego intenté usar CheckConstraint :
class Example(Model): ... class Meta: constraints = [ models.CheckConstraint(check=Q(uid_cnt=1), name='unique_uid') ] Esto falla porque no puede encontrar un campo en la instancia llamada uid_cnt , sin embargo, pensé que las anotaciones eran accesibles para los objetos Q Parece que las consultas de CheckConstraint contra el modelo directamente en lugar de usar el conjunto de consultas devuelto por el administrador:
class CheckConstraint(BaseConstraint): ... def _get_check_sql(self, model, schema_editor): query = Query(model=model) ...¿Hay alguna manera de aplicar una restricción a una anotación? ¿O hay un mejor enfoque?
Realmente me gustaría hacer cumplir esto en la capa db.
Gracias.
Esto es pseudocódigo, pero intente:
class Example(Model): ... class Meta: constraints = [ models.UniqueConstraint( fields=['type', 'timestamp__year', 'number'], condition=Q(number__isnull=False), name='unique_uid' ) ]