Поле является обязательным, даже если в сериализаторе оно явно установлено как необязательное

У меня возникли проблемы с маршрутом, создающим/обновляющим модель, DRF запрашивает поле, которое я установил как необязательное, и оно работает с другими сериализаторами, но не со специфическим.

Запрос (здесь нас интересует вложенный объект затрат) :

 {
   "building_block_id":"bd750fa0-d41d-492d-adc1-9aa7c50db232",
   "building_block_type_ids":"6fb5b907-9597-45fd-bb77-e93a2456cca3",
   "approbation_user":"",
   "approved":false,
   "name":"BB2",
   "web_doc_link":"",
   "author":"",
   "cms":"",
   "part_number":"",
   "manufacturer":"",
   "description":"T",
   "available_stock":null,
   "include_bench_output_connector":true,
   "base_repository":"",
   "form_factor_id":null,
   "direction_bench_side":null,
   "cost_references":[
      {
         "cost":2,
         "cost_date":"2021-11-03",
         "cost_quantity":2,
         "fab_cycle_time_days":2
      }
   ],
   "coupling":[
      {
         "developped":false,
         "tested":false,
         "validated":false,
         "delivered":false,
         "valid_link":"",
         "implem_link":"",
         "software_version_id":"62f4c9f8-1156-4b41-af1a-22041b824d06"
      }
   ],
   "comments":[
      
   ],
   "features":[
      
   ],
   "provides":[
      
   ],
   "requires":[
      
   ]
}

Ошибка, возвращаемая Django :

{
    "coupling": [
        {
            "building_block_id": [
                "This field is required."
            ]
        }
    ]
}

Класс сериализатора :

class BuildingBlockSerializer(serializers.ModelSerializer):
    cost_references = NestedCostReferenceSerializer(many=True, required=False)
    coupling = NestedCouplingSerializer(many=True, required=False)
    comments = NestedBuildingBlockCommentsSerializer(many=True, required=False)
    features = NestedFeaturesBuildingBlockSerializer(many=True, required=False)
    provides = NestedProvidesSerializer(many=True, required=False)
    requires = NestedRequiresSerializer(many=True, required=False)
    main_picture_link = Base64ImageField(required=False)
    front_picture_link = Base64ImageField(required=False)
    back_picture_link = Base64ImageField(required=False)

    # Related names for reverse relationship
    cost_reference_rel_name = 'cost_references'
    coupling_rel_name = 'coupling'
    comment_rel_name = 'comments'
    feature_rel_name = 'features'
    provide_rel_name = 'provides'
    require_rel_name = 'requires'

    class Meta:
        model = building_blocks.BuildingBlock
        fields = ['building_block_id', 'building_block_type_ids', 'approbation_user',
                  'approved', 'name', 'main_picture_link', 'front_picture_link', 'back_picture_link',
                  'web_doc_link', 'author', 'cms', 'part_number', 'manufacturer', 'description',
                  'available_stock', 'include_bench_output_connector', 'base_repository',
                  'form_factor_id', 'direction_bench_side', 'cost_references', 'coupling',
                  'comments', 'features', 'provides', 'requires']
        optional_fields = ['approved', ]
        extra_kwargs = {'approbation_user': {'required': False},
                        'building_block_type_ids': {'required': False},
                        'approved': {'required': False, 'allow_null': True},
                        'main_picture_link': {'required': False},
                        'front_picture_link': {'required': False},
                        'back_picture_link': {'required': False},
                        'web_doc_link': {'required': False},
                        'author': {'required': False},
                        'cms': {'required': False},
                        'part_number': {'required': False},
                        'manufacturer': {'required': False},
                        'available_stock': {'required': False, 'allow_null': True},
                        'include_bench_output_connector': {'required': False},
                        'base_repository': {'required': False},
                        'form_factor_id': {'required': False, 'allow_null': True},
                        'direction_bench_side': {'required': False, 'allow_null': True}}
...

Подсериализатор и вложенный сериализатор :

    class CouplingSerializer(serializers.ModelSerializer):
    class Meta: 
        model = building_blocks.Coupling
        fields = '__all__'


class NestedCouplingSerializer(CouplingSerializer):
    class Meta(CouplingSerializer.Meta):
        extra_kwargs = {
            "building_block_id": {"required": False},
            "building_block_history_id": {"required": False},
        }

Модель сцепления :

class Coupling(models.Model):
    building_block_id = models.ForeignKey(BuildingBlock, related_name='coupling', on_delete=models.CASCADE)
    software_version_id = models.ForeignKey('SoftwaresVersion', on_delete=models.CASCADE)
    developped = models.BooleanField()
    tested = models.BooleanField()
    validated = models.BooleanField()
    delivered = models.BooleanField()
    valid_link = models.CharField(max_length=256, null=True, blank=True)
    implem_link = models.CharField(max_length=256, null=True, blank=True)

    class Meta:
        unique_together = ['building_block_id', 'software_version_id']

При удалении переменной unique_together все работает нормально. Я бы хотел оставить эту настройку, но чтобы валидация проходила.

Я пытался установить валидаторы на [], но безрезультатно.

Изменение

unique_together = ['building_block_id', 'software_version_id']

To

constraints = [models.UniqueConstraint(fields=['building_block_id', 'software_version_id'], name='unique_coupling')]

Снято ограничение, вероятно, из-за некоторой валидации поля unique_together со стороны DRF.

Вернуться на верх