@@ -149,6 +149,14 @@ class Meta:
149
149
unique_together = ('race_name' , 'position' )
150
150
151
151
152
+ class BlankUniquenessTogetherModel (models .Model ):
153
+ race_name = models .CharField (max_length = 100 , blank = True )
154
+ position = models .IntegerField ()
155
+
156
+ class Meta :
157
+ unique_together = ('race_name' , 'position' )
158
+
159
+
152
160
class NullUniquenessTogetherModel (models .Model ):
153
161
"""
154
162
Used to ensure that null values are not included when checking
@@ -176,6 +184,12 @@ class Meta:
176
184
fields = '__all__'
177
185
178
186
187
+ class BlankUniquenessTogetherSerializer (serializers .ModelSerializer ):
188
+ class Meta :
189
+ model = BlankUniquenessTogetherModel
190
+ fields = '__all__'
191
+
192
+
179
193
class NullUniquenessTogetherSerializer (serializers .ModelSerializer ):
180
194
class Meta :
181
195
model = NullUniquenessTogetherModel
@@ -461,6 +475,34 @@ def test_do_not_ignore_validation_for_null_fields(self):
461
475
serializer = NullUniquenessTogetherSerializer (data = data )
462
476
assert not serializer .is_valid ()
463
477
478
+ def test_validation_for_provided_blank_fields (self ):
479
+ BlankUniquenessTogetherModel .objects .create (
480
+ position = 1
481
+ )
482
+ data = {
483
+ 'race_name' : '' ,
484
+ 'position' : 1
485
+ }
486
+ serializer = BlankUniquenessTogetherSerializer (data = data )
487
+ assert not serializer .is_valid ()
488
+
489
+ def test_validation_for_missing_blank_fields (self ):
490
+ BlankUniquenessTogetherModel .objects .create (
491
+ position = 1
492
+ )
493
+ data = {
494
+ 'position' : 1
495
+ }
496
+ serializer = BlankUniquenessTogetherSerializer (data = data )
497
+ assert not serializer .is_valid ()
498
+
499
+ def test_ignore_validation_for_missing_blank_fields (self ):
500
+ data = {
501
+ 'position' : 1
502
+ }
503
+ serializer = BlankUniquenessTogetherSerializer (data = data )
504
+ assert serializer .is_valid (), serializer .errors
505
+
464
506
def test_ignore_validation_for_unchanged_fields (self ):
465
507
"""
466
508
If all fields in the unique together constraint are unchanged,
@@ -589,6 +631,18 @@ class Meta:
589
631
]
590
632
591
633
634
+ class UniqueConstraintBlankModel (models .Model ):
635
+ title = models .CharField (max_length = 100 , blank = True )
636
+ age = models .IntegerField ()
637
+ tag = models .CharField (max_length = 100 , blank = True )
638
+
639
+ class Meta :
640
+ constraints = [
641
+ # Unique constraint on 2 blank fields
642
+ models .UniqueConstraint (name = 'unique_constraint' , fields = ('age' , 'tag' ), condition = ~ models .Q (models .Q (title = '' ) & models .Q (tag = 'True' )))
643
+ ]
644
+
645
+
592
646
class UniqueConstraintNullableModel (models .Model ):
593
647
title = models .CharField (max_length = 100 )
594
648
age = models .IntegerField (null = True )
@@ -607,6 +661,12 @@ class Meta:
607
661
fields = '__all__'
608
662
609
663
664
+ class UniqueConstraintBlankSerializer (serializers .ModelSerializer ):
665
+ class Meta :
666
+ model = UniqueConstraintBlankModel
667
+ fields = ('title' , 'age' , 'tag' )
668
+
669
+
610
670
class UniqueConstraintNullableSerializer (serializers .ModelSerializer ):
611
671
class Meta :
612
672
model = UniqueConstraintNullableModel
@@ -714,6 +774,12 @@ def test_single_field_uniq_validators(self):
714
774
ids_in_qs = {frozenset (v .queryset .values_list (flat = True )) for v in validators if hasattr (v , "queryset" )}
715
775
assert ids_in_qs == {frozenset ([1 ]), frozenset ([3 ])}
716
776
777
+ def test_blank_uqnique_constraint_fields_are_not_required (self ):
778
+ serializer = UniqueConstraintBlankSerializer (data = {'age' : 25 })
779
+ self .assertTrue (serializer .is_valid (), serializer .errors )
780
+ result = serializer .save ()
781
+ self .assertIsInstance (result , UniqueConstraintBlankModel )
782
+
717
783
def test_nullable_unique_constraint_fields_are_not_required (self ):
718
784
serializer = UniqueConstraintNullableSerializer (data = {'title' : 'Bob' })
719
785
self .assertTrue (serializer .is_valid (), serializer .errors )
0 commit comments