Найден третий способ реализации ограничений, чтобы было более очевидно, что значения NULL
считаются правильно с использованием двух ограничений:
from django.db import models
class Event( models.Model ):
start_date = models.DateField( blank = True, null = True )
start_time = models.TimeField( blank = True, null = True )
end_date = models.DateField( blank = True, null = True )
end_time = models.TimeField( blank = True, null = True )
class Meta:
constraints = [
# Option 3
models.CheckConstraint(
check = ( models.Q( start_date__isnull = True )
| models.Q( end_date__isnull = True )
| models.Q( start_date__lte = models.F( 'end_date' ) )
),
name = 'start_date_lte_end_date'
),
models.CheckConstraint(
check = ( models.Q( start_date__isnull = True )
| models.Q( end_date__isnull = True )
| models.Q( start_date__lt = models.F( 'end_date' ) )
| models.Q( start_time__isnull = True )
| models.Q( end_time__isnull = True )
| models.Q( start_time__lte = models.F( 'end_time' ) )
),
name = 'not_start_date_eq_end_date_and_start_time_gt_end_time'
),
]
Два ограничения будут перекрываться точно в случаях, когда:
start_date
равно нулю; end_date
равно нулю;или start_date < end_date
Остальные способы проверки могут проходить, когда первое ограничение равно start_date = end_date
, а второе ограничение:
start_time
равно нулю; end_time
равно нулю;или start_time <= end_time
Что соответствует всем возможным случаям в Варианте 1.
При дальнейшем тестировании модель с приведенными ниже ограничениями демонстрирует то же самоепроблема:
class SimpleModel( models.Model ):
value = models.IntegerField()
class Meta:
constraints = [
models.CheckConstraint(
check = ( models.Q( value__gte = 0 )
& ( models.Q( value__gte = 0 )
| models.Q( value__gte = 0 ) # this line
)
),
name = "simplemodel_check1"
),
models.CheckConstraint(
check = ( models.Q( value__gte = 0 )
& ( models.Q( value__gte = 0 )
& models.Q( value__gte = 0 )
)
),
name = "simplemodel_check2"
),
models.CheckConstraint(
check = ( models.Q( value__gte = 0 ) | models.Q( value__gte = 0 ) ),
name = "simplemodel_check3"
),
models.CheckConstraint(
check = ( models.Q( value__gte = 0 ) & models.Q( value__gte = 0 ) ),
name = "simplemodel_check4"
),
]
2-е, 3-е и 4-е ограничения работают без проблем, но 1-е ограничение вызывает исключение при попытке создать экземпляр модели с ошибкой:
django.db.utils.DatabaseError: malformed database schema (packagename_event) - no such column: new_packagename_simplemodel.value
Кажется, это проблема с комбинацией &
и |
.