def get_class(self, class_container, collection): """ Utitily method for getting the generated class based on the given collection. """ if not class_container: raise utils.DRFAdapterException( 'Classes have not been constructed yet. Run %s.construct()' % ( self.__class__.__name__)) if collection not in class_container: raise utils.DRFAdapterException( 'Class not found for collection %s' % (collection)) return class_container[collection]
def construct_drf_field(self, instance, spec, loc, context): """ Constructor of `.drf_field` predicate. This constructor validates the existence of a django model field to the extracted model class. In case of nested fields, e.g. `.struct`, `.structarray`, the field should be related to another model. """ parent = context.get('parent_name') field_constructors = { '.identity': self.construct_identity_field, } all_constructors = context.get('all_constructors') constructed = context.get('constructed') if len(constructed) < len(all_constructors) - 1: raise doc.DeferConstructor type_predicate = self.extract_type(instance) if type_predicate is None: raise utils.DRFAdapterException( 'Cannot construct drf field `%s` without specifying its' ' type' % (parent)) return field_constructors.get( type_predicate, self.default_field_constructor)( instance, spec, loc, context, type_predicate)
def _validate_model_attribute(api_field_name, model, model_attr_name): """ Checks that model have an attribute named as `model_attr_name`.""" model_attr = getattr(model, model_attr_name, None) if model_attr is None: raise utils.DRFAdapterException( 'Attribute %s (%s) not found in model %s' % ( model_attr_name, api_field_name, model.__name__)) return model_attr
def _validate_relational_field(api_field_name, ref_model, model_field): """ Checks that the given model field is related to the model given as parameter. """ if model_field.related_model is not ref_model: raise utils.DRFAdapterException( 'Model field of %s is not related to %s.' % ( model_field.name, ref_model)) return model_field
def extract_related_model(self, related_field, django_conf): """ Extracts related model based on given field. It also checks that given field is related to another model. """ model = self.extract_model(related_field, django_conf) related_field = model._meta.get_field(related_field) if related_field.related_model is None: raise utils.DRFAdapterException( 'Field %s is not related with another model' % ( repr(related_field))) return related_field.related_model
def _validate_configuration(self): meta_cls = getattr(self, 'Meta', None) if meta_cls is None: raise utils.DRFAdapterException('`Meta` class cannot be found') model_fields = getattr(meta_cls, 'model_fields', []) fields = getattr(meta_cls, 'extra_fields', []) if not (fields or model_fields): raise utils.DRFAdapterException( '`extra_fields` and `model_fields` attributes are unspecified') if not (self.model_ser_cls or self.ser_cls): raise utils.DRFAdapterException( 'A `ContainerSerializer` must define a `ModelSerializer` class' ' or a `Serializer class') if not (self.model_ser_cls or self.ser_cls): raise utils.DRFAdapterException( 'A `ContainerSerializer` must include a ModelSerializer' ' and Serializer class') if self.model_ser_cls: mro = inspect.getmro(self.model_ser_cls) if serializers.HyperlinkedModelSerializer not in mro: raise utils.DRFAdapterException( 'A model serializer class must inherit' ' `serializers.ModelSerializer`') if self.ser_cls: mro = inspect.getmro(self.ser_cls) if serializers.BaseSerializer not in mro: raise utils.DRFAdapterException( 'A serializer class must implement' ' `serializers.BaseSerializer`') return model_fields, fields
def validate_intersectional_pairs(self, properties): """ Validate properties of fields. There are some properties that cannot be set together, such as `required` and `readonly`. This method checks for such violations and raises an exception in this case. """ for field_name, prop in properties.iteritems(): for u, v in self.NON_INTERSECTIONAL_PAIRS: if prop.get(u, False) and prop.get(v, False): raise utils.DRFAdapterException( 'Field `%s` cannot be both %s and %s' % ( field_name, u, v))
def apply(self): """ Create django rest views based on the constructed adapter spec. """ if not self.adapter_spec: raise utils.DRFAdapterException( 'Cannot apply an empty adapter specification') structural_elements = self.get_structural_elements(self.adapter_spec) api = structural_elements[0] router = routers.DefaultRouter() for collection, spec in doc.doc_get( self.adapter_spec, (api,)).iteritems(): view = spec.get(self.ADAPTER_CONF) router.register(collection, view, base_name=collection) self.urls = url(r'^' + api + '/', include(router.urls))
def construct_property(self, instance, spec, loc, context, property_name): """ Constuctor for predicates that indicate a property of a field, e.g. nullable, readonly, required, etc. This constructor generates the corresponding cerberus syntax. However, it requires field to be initialized, otherwise, construction is defered. """ if property_name not in self.PROPERTY_MAPPING: raise utils.DRFAdapterException( 'Unknown property `%s`' % (property_name)) self.init_adapter_conf(instance) instance[self.ADAPTER_CONF].update( {self.PROPERTY_MAPPING[property_name]: True}) return instance
def _validate_model_type(api_field_name, model_field, django_field_type): """ Checks that the type of the specified model field matches with the `django_field_type` passed as parameter. `django_field_type` may be an iterable of types. If at least one type matches with the type of given model field, then we have a match. """ if isinstance(django_field_type, Iterable): matches = any(isinstance(model_field, d_field) for d_field in django_field_type) else: matches = isinstance(model_field, django_field_type) if not matches: raise utils.DRFAdapterException( 'Field %s is not %s type in your django model' % ( repr(api_field_name), repr(django_field_type))) return model_field
def validate_model_field(self, spec, name, loc, django_field_type, source=None): """ Validate that a field specified in spec is field of the model given as input. """ django_conf = self.get_constructor_params(spec, loc[:-1], []) model = self.extract_model(source or name, django_conf) automated = True if model is None: raise utils.DRFAdapterException( 'Invalid argument, model cannot be `None`') try: model_field = model._meta.get_field(source or name) model_attr = _validate_model_type(name, model_field, django_field_type) except FieldDoesNotExist: automated = False model_attr = _validate_model_attribute( name, model, source or name) return model_attr, model, automated
def default_field_constructor(self, instance, spec, loc, context, predicate_type): """ A common constructor for the drf fields. There are two cases: * If the field is a model field, then it does not initialize a `serializers.Field` object, but it stores all its properties in dictionary in order to be initialized later from the serializer. * If the field is a non-model field or its type is either `.struct` or `.structarry`, then the corresponding `serializers.Field` is contructed. Moreover, this method checks if the field conforms to the model configuations before being constructed. """ model, automated = self.validate_model_configuration( instance, spec, loc, context, predicate_type) path = (self.ADAPTER_CONF,) instance_source = spec.pop('instance_source', None) onmodel = spec.get('onmodel', True) if instance_source and onmodel: raise utils.DRFAdapterException( 'You don\'t have to specify `instance_source` if' ' `onmodel` is set') field_kwargs = {k: v for k, v in spec.iteritems() if k != 'onmodel'} field_kwargs.update(doc.doc_get(instance, path) or {}) if predicate_type == '.ref': field_kwargs.update(self._get_ref_params( instance, loc, context.get('top_spec'), onmodel and automated, field_kwargs)) doc.doc_set(instance, (self.ADAPTER_CONF, 'source'), instance_source) drf_field = self._generate_field( instance, context.get('parent_name'), predicate_type, model, automated and onmodel, **field_kwargs) doc.doc_set(instance, (self.ADAPTER_CONF, 'field'), drf_field) return instance
def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except FieldDoesNotExist as e: raise utils.DRFAdapterException(e)