예제 #1
0
 def __init__(self, model: Type[models.Model],
              model_pool: List[Type[models.Model]], type_url):
     self.model = model
     self.model_pool = model_pool
     self.type_url = type_url
     self.model_inspector = ModelInspector(model=model)
     self.fields = [
         Field(field, model_pool=model_pool)
         for field in self.model_inspector.model_fields()
     ]
예제 #2
0
 def __init__(self,
              model: Type[models.Model],
              model_pool: List[Type[models.Model]],
              parent: 'QuerysetLookups' = None,
              prefixes: List[str] = None,
              visited_models=None):
     self.model = model
     self.model_pool = model_pool
     self.parent = parent
     self.prefixes = prefixes if prefixes is not None else []
     self.visited_models = visited_models if visited_models is not None else []
     self.model_inspector = ModelInspector(model)
예제 #3
0
 def __init__(self, model: Type[models.Model],
              model_pool: List[Type[models.Model]], type_url):
     self.model = model
     self.model_pool = model_pool
     self.type_url = type_url
     self.model_inspector = ModelInspector(model=model)
     self.queryset_lookups = QuerysetLookups(model=model,
                                             model_pool=model_pool)
예제 #4
0
 def reverse_lookup_key(self):
     inspector = ModelInspector(model=self.field.related_model)
     return inspector.fk_field_to_model(
         model=self.field.model).name + '__id'
예제 #5
0
class QuerysetLookups(object):
    """
    Helper class for rendering "type declarations" for Queryset lookups.

    """
    def __init__(self,
                 model: Type[models.Model],
                 model_pool: List[Type[models.Model]],
                 parent: 'QuerysetLookups' = None,
                 prefixes: List[str] = None,
                 visited_models=None):
        self.model = model
        self.model_pool = model_pool
        self.parent = parent
        self.prefixes = prefixes if prefixes is not None else []
        self.visited_models = visited_models if visited_models is not None else []
        self.model_inspector = ModelInspector(model)

    def _lookup_key(self, suffixes: List[str] = None):
        if suffixes is None:
            suffixes = []
        return "__".join(self.prefixes + suffixes)

    def type_declarations(self):
        type_declarations = list()
        for field in self.model_inspector.model_fields():
            type_declarations += self._field_type_declarations(field=field)
        return type_declarations

    def _field_type_declarations(self, field: models.Field):
        type_declarations = list()
        # If the field is relational, check that it is in the `model_pool`, and that
        # it has not already been "visited" (to prevent an infinite cycle).
        if isinstance(
                field,
            (models.ForeignKey, models.OneToOneField, models.ManyToOneRel)):
            if (field.related_model
                    in self.model_pool) and (field.related_model
                                             not in self.visited_models):
                child_queryset_lookups = QuerysetLookups(
                    model=field.related_model,
                    model_pool=self.model_pool,
                    prefixes=self.prefixes + [field.name],
                    visited_models=self.visited_models + [self.model])
                type_declarations += child_queryset_lookups.type_declarations()
        if not isinstance(field, models.ManyToOneRel):
            # This is the base lookup for the field.
            type_declarations.append(
                self._lookup_key([field.name]) + "? : " +
                self._lookup_type(field, None))

            for lookup_str, lookup_cls in field.get_lookups().items():
                type_declarations.append(
                    self._lookup_key([field.name, lookup_str]) + "? : " +
                    self._lookup_type(field, lookup_cls))
        return type_declarations

    @staticmethod
    def _lookup_type(field, lookup_cls) -> str:
        if lookup_cls in TypeTranspiler.CONTAINER_TYPES:
            return TypeTranspiler.CONTAINER_TYPES[lookup_cls](
                TypeTranspiler.transpile(field))
        return TypeTranspiler.transpile(field)
예제 #6
0
 def _test_get_fk_fields(self):
     inspector = ModelInspector(ThingChild)
     self.assertEqual(inspector.foreign_key_fields(), [ThingChild.parent])
예제 #7
0
 def test_get_fk_field_to_model(self):
     inspector = ModelInspector(ThingChild)
     self.assertEqual(inspector.fk_field_to_model(Thing).name, 'parent')
예제 #8
0
 def test_get_pk_field(self):
     inspector = ModelInspector(Thing)
     self.assertEqual(inspector.pk_field_name, 'id')
예제 #9
0
class Model(object):

    """
    Class for rendering a TypeScript `rests` model.

    """

    TEMPLATE = """
    // -------------------------
    // {{ model.name }}
    //
    // -------------------------

    interface {{ model.interface_type_name }} {
    {% for type_dec in model.field_interface_type_declarations %}{{ type_dec }}, \n{% endfor %}
    }


    export class {{ model.name }} extends Model {

        static BASE_URL = '/{{ model.type_url }}';
        static PK_FIELD_NAME = '{{ model.pk_field_name }}';
        static FIELDS = [{{ model.literal_field_names }}];

        static objects = {{ model.queryset_cls_name }};
        static serverClient = serverClient;

        {% for type_dec in model.field_cls_type_declarations %}{{ type_dec }};\n{% endfor %}

        constructor({ {{ model.field_names|join(',') }} }: {{ model.interface_type_name }}){
        super({ {{ model.field_names|join(',') }} })
        }

        public async update(data: Partial<{{ model.interface_type_name }}>, responseHandlers: ResponseHandlers={}): Promise<{{ model.name }}>{
            Object.keys(data).map((fieldName) => {
            this[fieldName] = data[fieldName];
        });
        await this.save();
        return this;
        }

        {% for field in model.reverse_relation_fields %}
        public {{ field.name }}(lookups: {{ field.related_model_name }}Lookups = {}){
            return new {{ field.related_model_name }}Queryset({...lookups, ...{ {{ field.reverse_lookup_key }}: this.pk()}})
        }
        {% endfor %}

    }

    {{ model.queryset_cls_name }}.Model = {{ model.name }};

        """

    def __init__(self, model: Type[models.Model], model_pool: List[Type[models.Model]], type_url):
        self.model = model
        self.model_pool = model_pool
        self.type_url = type_url
        self.model_inspector = ModelInspector(model=model)
        self.fields = [Field(field) for field in self.model_inspector.model_fields()]

    @property
    def name(self):
        return self.model_inspector.model_name

    @property
    def pk_field_name(self):
        return self.model_inspector.pk_field_name

    @property
    def interface_type_name(self):
        """ Return the name given to the type interface for this model. """
        return self.name + "Data"

    @property
    def field_names(self):
        field_names = list()
        for field in self.fields:
            field_names += field.names()
        return field_names

    @property
    def literal_field_names(self):
        return ", ".join("'{}'".format(f) for f in self.field_names)

    @property
    def field_interface_type_declarations(self):
        type_declarations = list()
        for field in self.fields:
            type_declarations += field.interface_type_declarations()
        return type_declarations

    @property
    def field_cls_type_declarations(self):
        type_declarations = list()
        for field in self.fields:
            type_declarations += field.cls_type_declarations()
        return type_declarations

    @property
    def queryset_cls_name(self):
        return self.name + "Queryset"

    @property
    def reverse_relation_fields(self):
        return [f for f in self.fields if f.is_reverse_relation]

    def render(self):
        return Template(self.TEMPLATE).render(model=self)