示例#1
0
 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]
示例#2
0
    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)
示例#3
0
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
示例#4
0
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
示例#5
0
 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
示例#6
0
 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
示例#7
0
    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))
示例#8
0
 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))
示例#9
0
    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
示例#10
0
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
示例#11
0
 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
示例#12
0
    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
示例#13
0
 def wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except FieldDoesNotExist as e:
         raise utils.DRFAdapterException(e)