def get_serializer_fields(self, path, method): """ Return a list of `coreapi.Field` instances corresponding to any request body input, as determined by the serializer class. """ view = self.view method_name = getattr(view, 'action', method.lower()) parser_serializer = getattr(getattr(view, method_name), "_parser_serializer", None) if method not in ('PUT', 'PATCH', 'POST', 'DELETE'): return [] if parser_serializer and isinstance(parser_serializer, serializers.Serializer): fields = [] for field in parser_serializer.fields.values(): if field.read_only or isinstance(field, serializers.HiddenField): continue required = field.required and method != 'PATCH' field = coreapi.Field(name=field.field_name, location='form', required=required, schema=field_to_schema(field)) fields.append(field) return fields else: return super(CustomerSchema, self).get_serializer_fields(path, method)
def get_response_object(self, response_serializer_class, description): fields = [] serializer = response_serializer_class() nested_obj = {} for field in serializer.fields.values(): # If field is a serializer, attempt to get its schema. if isinstance(field, serializers.Serializer): subfield_schema = self.get_response_object( field.__class__, None)[0].get('schema') # If the schema exists, use it as the nested_obj if subfield_schema is not None: nested_obj[field.field_name] = subfield_schema nested_obj[ field.field_name]['description'] = field.help_text continue # Otherwise, carry-on and use the field's schema. fallback_schema = self.fallback_schema_from_field(field) fields.append( Field( name=field.field_name, location='form', required=field.required, schema=fallback_schema if fallback_schema else field_to_schema(field), )) res = _get_parameters(Link(fields=fields), None) if not res: if nested_obj: return { 'description': description, 'schema': { 'type': 'object', 'properties': nested_obj } }, {} else: return {}, {} schema = res[0]['schema'] schema['properties'].update(nested_obj) response_schema = {'description': description, 'schema': schema} error_status_codes = {} response_meta = getattr(response_serializer_class, 'Meta', None) for status_code, description in getattr(response_meta, 'error_status_codes', {}).items(): error_status_codes[status_code] = {'description': description} return response_schema, error_status_codes
def get_serializer_fields(self, path, method, view, version=None, method_func=None): """ Return a list of `coreapi.Field` instances corresponding to any request body input, as determined by the serializer class. """ if method in ('PUT', 'PATCH', 'POST'): location = 'form' else: location = 'query' serializer_class = self.get_serializer_class(view, method_func) if not serializer_class: return [] serializer = serializer_class() if isinstance(serializer, serializers.ListSerializer): return [ Field(name='data', location=location, required=True, schema=coreschema.Array()) ] if not isinstance(serializer, serializers.Serializer): return [] fields = [] for field in serializer.fields.values(): if field.read_only or isinstance(field, serializers.HiddenField): continue required = field.required and method != 'PATCH' # if the attribute ('help_text') of this field is a lazy translation object, force it to generate a string description = str(field.help_text) if isinstance( field.help_text, Promise) else field.help_text fallback_schema = self.fallback_schema_from_field(field) field = Field( name=field.field_name, location=location, required=required, schema=fallback_schema if fallback_schema else field_to_schema(field), description=description, ) fields.append(field) return fields
def add_object_definitions(self, method, view): """Create an Object definition from serializer It will create a different definitions depending on the method, definition name is {serializer class name}_{read|write} POST, PUT, PATCH is write GET, DELETE, HEAD is read write methods will not include read only fields read methods will not include write only fields Note that for write methods it will also return a read definition because by default this is the definition object returned by write methods :param str method: GET, POST etc :param rest_framework.generics.GenericAPIView view: """ if not hasattr(view, 'get_serializer'): return None try: serializer = view.get_serializer() except AssertionError: # Default behaviour of GenericAPIView is to raise AssertionError return None if method in ('POST', 'PUT', 'PATCH'): write = True # also generate a read definition, because it is commonly used as response for write actions self.add_object_definitions('GET', view) name = '%s_write' % serializer.__class__.__name__ elif method in ('GET', 'DELETE', 'HEAD'): write = False name = '%s_read' % serializer.__class__.__name__ else: assert False, 'Can not recognize method %s' % method if name in self.definitions: return fields = [] for field in serializer.fields.values(): if isinstance(field, serializers.HiddenField) or write and field.read_only or \ not write and field.write_only: continue # required = bool(field.required) # field.required is a list field = field_to_schema(field) fields.append(field) self.definitions[name] = coreschema.Object(title=name, properties=fields) return self.definitions[name]
def test_field_to_schema(self): label = 'Test label' help_text = 'This is a helpful test text' cases = [ # tuples are ([field], [expected schema]) # TODO: Add remaining cases ( serializers.BooleanField(label=label, help_text=help_text), coreschema.Boolean(title=label, description=help_text) ), ( serializers.DecimalField(1000, 1000, label=label, help_text=help_text), coreschema.Number(title=label, description=help_text) ), ( serializers.FloatField(label=label, help_text=help_text), coreschema.Number(title=label, description=help_text) ), ( serializers.IntegerField(label=label, help_text=help_text), coreschema.Integer(title=label, description=help_text) ), ( serializers.DateField(label=label, help_text=help_text), coreschema.String(title=label, description=help_text, format='date') ), ( serializers.DateTimeField(label=label, help_text=help_text), coreschema.String(title=label, description=help_text, format='date-time') ), ( serializers.JSONField(label=label, help_text=help_text), coreschema.Object(title=label, description=help_text) ), ] for case in cases: self.assertEqual(field_to_schema(case[0]), case[1])