@@ -1346,6 +1346,31 @@ class Meta:
1346
1346
fields = ('name' ,)
1347
1347
1348
1348
1349
+ class UniqueTestModel (models .Model ):
1350
+ name = models .CharField (max_length = 100 )
1351
+ description = models .CharField (max_length = 100 , null = True , blank = True )
1352
+ other_field = models .CharField (max_length = 100 , default = "default_value" )
1353
+
1354
+ class Meta :
1355
+ unique_together = [("name" , "description" )]
1356
+
1357
+ def __str__ (self ):
1358
+ return f"{ self .name } - { self .description or 'No description' } "
1359
+
1360
+
1361
+ class UniqueTestModelSerializer (serializers .ModelSerializer ):
1362
+ description = serializers .SerializerMethodField ()
1363
+
1364
+ class Meta :
1365
+ model = UniqueTestModel
1366
+ fields = ["name" , "description" , "other_field" ]
1367
+
1368
+ def get_description (self , obj ):
1369
+ if obj .description :
1370
+ return f"Serialized: { obj .description } "
1371
+ return "Serialized: No description provided"
1372
+
1373
+
1349
1374
class Issue6110Test (TestCase ):
1350
1375
def test_model_serializer_custom_manager (self ):
1351
1376
instance = Issue6110ModelSerializer ().create ({'name' : 'test_name' })
@@ -1395,3 +1420,68 @@ class Meta:
1395
1420
serializer .save ()
1396
1421
1397
1422
self .assertEqual (instance .char_field , 'value changed by signal' )
1423
+
1424
+
1425
+ class TestSerializerMethodFieldInUniqueTogether (TestCase ):
1426
+ def test_serializer_method_field_not_hidden_in_unique_together (self ):
1427
+ """
1428
+ Tests that a SerializerMethodField named the same as a model field
1429
+ in a unique_together constraint is not treated as a HiddenField and
1430
+ that unique_together validation still functions correctly.
1431
+ """
1432
+ serializer = UniqueTestModelSerializer ()
1433
+
1434
+ self .assertFalse (
1435
+ isinstance (serializer .fields ['description' ], serializers .HiddenField ),
1436
+ "Field 'description' should not be a HiddenField."
1437
+ )
1438
+ self .assertTrue (
1439
+ isinstance (serializer .fields ['description' ], serializers .SerializerMethodField ),
1440
+ "Field 'description' should be a SerializerMethodField."
1441
+ )
1442
+
1443
+ instance = UniqueTestModel .objects .create (name = "TestName" , description = "TestDesc" )
1444
+ serializer_output = UniqueTestModelSerializer (instance ).data
1445
+ self .assertIn ("description" , serializer_output )
1446
+ self .assertEqual (serializer_output ["description" ], "Serialized: TestDesc" )
1447
+
1448
+ instance_no_desc = UniqueTestModel .objects .create (name = "TestNameNoDesc" )
1449
+ serializer_output_no_desc = UniqueTestModelSerializer (instance_no_desc ).data
1450
+ self .assertEqual (serializer_output_no_desc ["description" ], "Serialized: No description provided" )
1451
+
1452
+ UniqueTestModel .objects .create (name = "UniqueName" , description = "UniqueDesc" )
1453
+ invalid_data = {"name" : "UniqueName" , "description" : "UniqueDesc" , "other_field" : "some_value" }
1454
+ serializer_invalid = UniqueTestModelSerializer (data = invalid_data )
1455
+ with self .assertRaises (serializers .ValidationError ) as context :
1456
+ serializer_invalid .is_valid (raise_exception = True )
1457
+ self .assertIn ("non_field_errors" , context .exception .detail )
1458
+ self .assertTrue (any ("unique test model with this name and description already exists" in str (err )
1459
+ for err_list in context .exception .detail .values () for err in err_list ))
1460
+
1461
+ UniqueTestModel .objects .create (name = "UniqueNameNull" , description = None )
1462
+ invalid_data_null = {"name" : "UniqueNameNull" , "description" : None , "other_field" : "some_value" }
1463
+ serializer_invalid_null = UniqueTestModelSerializer (data = invalid_data_null )
1464
+ with self .assertRaises (serializers .ValidationError ) as context_null :
1465
+ serializer_invalid_null .is_valid (raise_exception = True )
1466
+ self .assertIn ("non_field_errors" , context_null .exception .detail )
1467
+ self .assertTrue (any ("unique test model with this name and description already exists" in str (err )
1468
+ for err_list in context_null .exception .detail .values () for err in err_list ))
1469
+
1470
+ valid_data = {"name" : "NewName" , "description" : "NewDesc" , "other_field" : "another_value" }
1471
+ serializer_valid = UniqueTestModelSerializer (data = valid_data )
1472
+ self .assertTrue (serializer_valid .is_valid (raise_exception = True ))
1473
+ self .assertEqual (serializer_valid .validated_data ['name' ], "NewName" )
1474
+
1475
+ valid_data_no_desc = {"name" : "NameOnly" }
1476
+ serializer_valid_no_desc = UniqueTestModelSerializer (data = valid_data_no_desc )
1477
+ self .assertTrue (serializer_valid_no_desc .is_valid (raise_exception = True ))
1478
+ self .assertIsNone (serializer_valid_no_desc .validated_data .get ('description' ))
1479
+ self .assertEqual (serializer_valid_no_desc .validated_data ['other_field' ], "default_value" )
1480
+
1481
+ saved_instance = serializer_valid_no_desc .save ()
1482
+ self .assertEqual (saved_instance .name , "NameOnly" )
1483
+ self .assertIsNone (saved_instance .description )
1484
+ self .assertEqual (saved_instance .other_field , "default_value" )
1485
+
1486
+ output_after_save = UniqueTestModelSerializer (saved_instance ).data
1487
+ self .assertEqual (output_after_save ['description' ], "Serialized: No description provided" )
0 commit comments