Пример #1
0
    def _get_value(self):
        primitive_models_dict = MetaModel.get_primitive_models_dict()

        mtype = primitive_models_dict.get(self.model_id, None)

        if mtype:
            mtype = mtype.name

            if mtype == 'BooleanField':
                return bool(self.decimal_value)
            if mtype == 'CharField':
                return self.unicode_value
            if mtype == 'DateField':
                return date.fromordinal(self.decimal_value)
            if mtype == 'DateTimeField':
                epoch = datetime.utcfromtimestamp(0)
                delta = timedelta(seconds=int(self.decimal_value))
                return epoch + delta
            if mtype == 'DecimalField':
                return self.decimal_value
            if mtype == 'FileField':
                return FieldFile(default_storage.open(self.unicode_value),
                                 FileField(), self.unicode_value)
            if mtype == 'IntegerField':
                return int(self.decimal_value)

        return self.__getattr__('value')
Пример #2
0
class ModelEditView(DetailView):
    queryset = MetaModel.get_non_primitive()
    template_name = 'metamodel/model_edit.html'

    def get_context_data(self, **kwargs):
        context = super(ModelEditView, self).get_context_data(**kwargs)

        form = MetaModelForm(instance=self.object)
        context['form'] = form

        return context

    def post(self, request, pk, *args, **kwargs):
        meta_model = self.get_object()

        form = MetaModelForm(request.POST, instance=meta_model)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(
                reverse('metamodel_model_meta',
                        kwargs={'pk': self.get_object().pk}))
        else:
            self.object = meta_model
            context = self.get_context_data(**kwargs)
            context['form'] = form
            return self.render_to_response(context)
Пример #3
0
    def delete(self, *args, **kwargs):
        primitive_instance_fields = self.fields.filter(
            value__model__in=MetaModel.get_primitive())

        for field in primitive_instance_fields:
            field.value.delete()

        return super(InstanceModel, self).delete(*args, **kwargs)
Пример #4
0
class ModelDeleteView(DetailView):
    queryset = MetaModel.get_non_primitive()
    template_name = 'metamodel/model_delete.html'

    def post(self, request, pk, *args, **kwargs):
        meta_model = self.get_object()
        meta_model.delete()

        return HttpResponseRedirect(reverse('metamodel_model_list'))
Пример #5
0
    def _set_value(self, new_value):
        mtype = MetaModel.get_primitive_models_dict()[self.model_id].name

        if mtype == 'BooleanField':
            if not isinstance(new_value, bool):
                raise ValueError

            self.decimal_value = int(new_value)
            self.unicode_value = None

        if mtype == 'CharField':
            if not isinstance(new_value, str):
                raise ValueError

            self.unicode_value = str(new_value)
            self.decimal_value = None

        if mtype == 'DateField':
            if not isinstance(new_value, date):
                raise ValueError

            self.decimal_value = new_value.toordinal()
            self.unicode_value = None

        if mtype == 'DateTimeField':
            if not isinstance(new_value, datetime):
                raise ValueError

            epoch = datetime.utcfromtimestamp(0)

            self.decimal_value = (new_value.replace(tzinfo=None) -
                                  epoch).total_seconds()
            self.unicode_value = None

        if mtype == 'DecimalField':
            self.decimal_value = Decimal(new_value)
            self.unicode_value = None

        if mtype == 'FileField':
            if isinstance(new_value, File):
                self.unicode_value = new_value.name
                self.decimal_value = None
                return

            if not isinstance(new_value, str):
                raise ValueError

            self.unicode_value = str(new_value)
            self.decimal_value = None

        if mtype == 'IntegerField':
            if not isinstance(new_value, int):
                raise ValueError

            self.decimal_value = new_value
            self.unicode_value = None
Пример #6
0
def unicode_function(im):
    m = MetaModel.get_model_by_id(im.model_id).name
    if m == 'VideoCardMemoryQuantity':
        value = im.value
        if value % 1024 == 0:
            return '{} GB'.format(value / 1024)
        elif value > 512 and (value - 512) % 1024 == 0:
            return '{}.5 GB'.format((value - 512) / 1024)
        else:
            return '{} MB'.format(value)
Пример #7
0
class ModelAddInstance(DetailView):
    queryset = MetaModel.get_non_primitive()
    template_name = 'metamodel/model_add_instance.html'

    def is_popup(self):
        return bool(self.request.GET.get('popup', False))

    def get_context_data(self, **kwargs):
        context = super(ModelAddInstance, self).get_context_data(**kwargs)
        context['form'] = self.object.get_form()()
        is_popup = self.is_popup()

        form_action = reverse('metamodel_model_add_instance',
                              kwargs={'pk': self.object.pk})

        if is_popup:
            form_action += '?popup=1'

        context['hide_nav'] = is_popup
        context['form_action'] = form_action
        return context

    def post(self, request, pk, *args, **kwargs):
        meta_model = self.get_object()

        form = meta_model.get_form()(request.POST, request.FILES)

        if form.is_valid():
            instance_model = InstanceModel()
            instance_model.model = meta_model

            instance_model.save(initial=True)
            instance_model.update_fields(form.cleaned_data,
                                         request.POST,
                                         creator_id=request.user.id)

            if self.is_popup():
                return HttpResponseRedirect(
                    reverse('metamodel_instance_popup_redirect',
                            kwargs={'pk': instance_model.pk}))
            else:
                messages.success(
                    request,
                    u'<a href={0}>{1}</a> creada correctamente'.format(
                        reverse('metamodel_instance_detail',
                                kwargs={'pk': instance_model.pk}),
                        str(instance_model)))
                return HttpResponseRedirect(
                    reverse('metamodel_model_detail',
                            kwargs={'pk': meta_model.pk}))
        else:
            self.object = meta_model
            context = self.get_context_data(**kwargs)
            context['form'] = form
            return self.render_to_response(context)
Пример #8
0
class ModelMetaView(DetailView):
    queryset = MetaModel.get_non_primitive()
    template_name = 'metamodel/model_meta.html'

    def post(self, request, pk, *args, **kwargs):
        meta_model = self.get_object()

        for field in meta_model.fields.all():
            if field.name in request.POST:
                field.ordering = int(request.POST[field.name])
                field.save()

        return HttpResponseRedirect(
            reverse('metamodel_model_meta', kwargs={'pk': meta_model.pk}))
Пример #9
0
    def get_or_create_with_value(cls, parent, field, value):
        from metamodel.models import MetaModel

        primitive_models_dict = MetaModel.get_primitive_models_dict()

        if field.multiple:
            raise Exception('This method is only consistent for '
                            'non-multiple fields')

        try:
            instance_field = cls.objects.get(parent=parent, field=field)

            if value is None or value == '':
                instance_field.delete()
                return None

            if field.model_id in primitive_models_dict:
                instance_field.value.value = value
                instance_field.value.save()
                return instance_field

        except cls.DoesNotExist:
            if value is None or value == '':
                return

            instance_field = InstanceField(parent=parent, field=field)

            if field.model_id in primitive_models_dict:
                instance_value = InstanceModel(model=field.model)
                instance_value.value = value
                instance_value.save()
                value = instance_value

        instance_field.value = value
        instance_field.save()

        return instance_field
Пример #10
0
def unicode_function(im):
    m = MetaModel.get_model_by_id(im.model_id).name
    if m == 'LightTube':
        specs = [str(im.l_type)]

        if im.consumption:
            if im.equivalent_power:
                specs.append(u'{} - {}W'.format(
                    im.consumption.quantize(0),
                    im.equivalent_power.quantize(0)))
            else:
                specs.append(u'{}W'.format(im.consumption.quantize(0)))
        else:
            if im.equivalent_power:
                specs.append(u'{}W Equivalente'.format(
                    im.equivalent_power.quantize(0)))

        specs.append(str(im.light_type))
        specs.append(str(im.length))

        name_value = im.name
        if name_value is None:
            name_value = ''

        result = u'{} {} {} ({})'.format(im.technology, im.brand, name_value,
                                         ' / '.join(specs))
        return ' '.join(result.split())
    if m == 'LightProjector':
        specs = []

        if im.consumption:
            if im.equivalent_power:
                specs.append(u'{} - {}W'.format(
                    im.consumption.quantize(0),
                    im.equivalent_power.quantize(0)))
            else:
                specs.append(u'{}W'.format(im.consumption.quantize(0)))
        else:
            if im.equivalent_power:
                specs.append(u'{}W Equivalente'.format(
                    im.equivalent_power.quantize(0)))

        specs.append(str(im.light_type))

        if im.has_movement_sensor:
            specs.append(u'Con sensor de movimimiento')

        name_value = im.name
        if name_value is None:
            name_value = ''

        result = u'{} {} {} ({})'.format(im.technology, im.brand, name_value,
                                         ' / '.join(specs))
        return ' '.join(result.split())
    if m == 'Lamp':
        specs = [str(im.socket), im.format.short_name]

        if im.consumption:
            if im.equivalent_power:
                specs.append(u'{} - {}W'.format(
                    im.consumption.quantize(0),
                    im.equivalent_power.quantize(0)))
            else:
                specs.append(u'{}W'.format(im.consumption.quantize(0)))
        else:
            if im.equivalent_power:
                specs.append(u'{}W Equivalente'.format(
                    im.equivalent_power.quantize(0)))

        specs.append(str(im.light_type))

        name_value = im.name
        if name_value is None:
            name_value = ''

        result = u'{} {} {} ({})'.format(im.l_type, im.brand, name_value,
                                         ' / '.join(specs))
        return ' '.join(result.split())
    if m == 'MemoryCardCapacity':
        if im.value % 1000 == 0:
            return u'{} TB'.format(im.value / 1000)
        elif im.value > 1000 and (im.value - 500) % 1000 == 0:
            return u'{}.5 TB'.format((im.value - 500) / 1000)
        else:
            return u'{} GB'.format(im.value)
    if m == 'MemoryCard':
        name_value = im.name
        if name_value is None:
            name_value = ''

        result = u'{} {} {} {}'.format(im.brand, name_value, im.type,
                                       im.capacity)

        if im.rated_speed.value:
            result += u' {}'.format(im.rated_speed)
        elif im.x_speed.value:
            result += u' {}'.format(im.x_speed)

        if im.sku:
            result += u' ({})'.format(im.sku)

        return result
    if m == 'UsbFlashDriveCapacity':
        if im.value % 1000 == 0:
            return u'{} TB'.format(im.value / 1000)
        elif im.value > 1000 and (im.value - 500) % 1000 == 0:
            return u'{}.5 TB'.format((im.value - 500) / 1000)
        else:
            return u'{} GB'.format(im.value)
    if m == 'UsbFlashDrive':
        if im.sku:
            return u'{} {} {} ({})'.format(im.line, im.name, im.capacity,
                                           im.sku)
        else:
            return u'{} {} {}'.format(im.line, im.name, im.capacity)
Пример #11
0
 def delete_non_used_primitives(cls):
     cls.objects.filter(model__in=MetaModel.get_primitive(),
                        fields_usage__isnull=True).delete()
Пример #12
0
    def __setattr__(self, name, value):
        if name in [
                'id', 'decimal_value', 'unicode_value',
                'unicode_representation', 'model_id', 'model'
        ]:
            return super(InstanceModel, self).__setattr__(name, value)

        primitive_models_dict = MetaModel.get_primitive_models_dict()

        if name == 'value' and self.model_id in primitive_models_dict:
            self._set_value(value)
            return

        if name.startswith('_'):
            return super(InstanceModel, self).__setattr__(name, value)

        from metamodel.models import InstanceField

        try:
            mf = MetaField.objects.get(parent=self.model, name=name)

            is_primitive = mf.model_id in primitive_models_dict

            if not mf.nullable and not mf.multiple and not is_primitive:
                if value is None:
                    raise IntegrityError('This field cannot be None')

                InstanceField.get_or_create_with_value(self, mf, value)
            if not mf.nullable and not mf.multiple and is_primitive:
                if value is None:
                    raise IntegrityError('This field cannot be None')

                InstanceField.get_or_create_with_value(self, mf, value)
            if mf.multiple and not is_primitive:
                InstanceField.objects.filter(field=mf, parent=self).delete()
                for individual_value in value:
                    new_field = InstanceField(
                        parent=self,
                        field=mf,
                    )

                    new_field.value = individual_value
                    new_field.save()

            if mf.multiple and is_primitive:
                existing_fields = InstanceField.objects.filter(field=mf,
                                                               parent=self)
                for field in existing_fields:
                    field.value.delete()

                for individual_value in value:
                    im = InstanceModel(model=mf.model)
                    im.value = individual_value
                    im.save()

                    new_field = InstanceField(
                        parent=self,
                        field=mf,
                    )

                    new_field.value = im
                    new_field.save()

            if mf.nullable and not mf.multiple and not is_primitive:
                InstanceField.get_or_create_with_value(self, mf, value)

            if mf.nullable and not mf.multiple and is_primitive:
                InstanceField.get_or_create_with_value(self, mf, value)

        except MetaField.DoesNotExist:
            return object.__setattr__(self, name, value)
Пример #13
0
    def elasticsearch_document(self):
        """
        Generates the elasticsearch document of the given InstanceModel
        based on its fields and unicode representation and automatically
        following all of its relations.
        """
        def sanitize_value(value):
            serialized_value = value

            if type(value) == Decimal:
                serialized_value = float(value)

            if type(value) == FieldFile:
                serialized_value = value.name

            try:
                json.dumps(serialized_value)
                return serialized_value
            except TypeError:
                raise

        if not self:
            return {}, []

        result = {u'id': self.id, u'unicode': str(self)}

        keywords = result[u'unicode'].split()

        meta_fields = MetaModel.get_metafields_by_model_id(self.model_id)

        instance_fields = self.fields.select_related()

        instance_values_dict = {
            instance_field.field: instance_field.value
            for instance_field in instance_fields
        }

        for meta_field in meta_fields:
            if meta_field.multiple:
                m2m_documents = []

                m2m_instance_fields = instance_fields.filter(
                    field=meta_field).select_related()

                if not m2m_instance_fields:
                    continue

                for m2m_instance_field in m2m_instance_fields:
                    m2m_document = m2m_instance_field.value\
                        .elasticsearch_document()

                    m2m_documents.append(m2m_document[0])
                    keywords.extend(m2m_document[1])

                keys = m2m_documents[0].keys()

                for key in keys:
                    key_subresult = [d[key] for d in m2m_documents]
                    result[meta_field.name + '_' + key] = key_subresult
            else:
                try:
                    instance_value = instance_values_dict[meta_field]
                except KeyError:
                    instance_value = None

                if meta_field.model.is_primitive():
                    value = instance_value
                    if value:
                        value = instance_value.value
                    result[meta_field.name] = sanitize_value(value)
                elif instance_value:
                    fk_result = instance_value.elasticsearch_document()
                    for fk_key, fk_value in fk_result[0].items():
                        try:
                            result[meta_field.name + '_' + fk_key] = \
                                sanitize_value(fk_value)
                        except TypeError:
                            pass

                    keywords.extend(fk_result[1])

        for function_path in settings.METAMODEL[
                'ADDITIONAL_ELASTICSEARCH_FIELDS_FUNCTIONS']:
            path_components = function_path.split('.')
            f_module = importlib.import_module('.'.join(path_components[:-1]))
            additional_es_fields_function = getattr(f_module,
                                                    path_components[-1])
            additional_fields = \
                additional_es_fields_function(self, result)
            if additional_fields:
                result.update(additional_fields)

        return result, keywords
Пример #14
0
class ModelDetailView(DetailView):
    queryset = MetaModel.get_non_primitive()
    template_name = 'metamodel/model_detail.html'
Пример #15
0
class ModelListView(ListView):
    queryset = MetaModel.get_non_primitive()
    template_name = 'metamodel/model_list.html'
Пример #16
0
class MetaModelAddFieldView(DetailView):
    queryset = MetaModel.get_non_primitive()
    template_name = 'metamodel/model_add_field.html'

    def get(self, request, *args, **kwargs):
        if request.is_ajax():
            model_type = request.GET['model']
            nullable = request.GET['nullable'] == 'true'
            multiple = request.GET['multiple'] == 'true'

            meta_model = self.get_object()

            requires_default = True

            if nullable or multiple:
                requires_default = False

            if not meta_model.instancemodel_set.all():
                requires_default = False

            default_choices = None

            if model_type:
                meta_model = MetaModel.objects.get(pk=model_type)
                if meta_model.is_primitive():
                    default_choices = meta_model.html_input_type()
                else:
                    default_choices = [
                        (e.pk, str(e))
                        for e in meta_model.instancemodel_set.all()
                    ]

            return HttpResponse(json.dumps([requires_default,
                                            default_choices]))

        else:
            return super(MetaModelAddFieldView,
                         self).get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(MetaModelAddFieldView, self).get_context_data(**kwargs)

        form = MetaModelAddFieldForm()
        context['form'] = form

        return context

    def post(self, request, pk, *args, **kwargs):
        meta_model = self.get_object()

        form = MetaModelAddFieldForm(data=request.POST, files=request.FILES)

        if form.is_valid():
            meta_field = form.instance
            meta_field.parent = meta_model

            if meta_field.requires_default_value_for_saving():
                if meta_field.model.name == 'FileField':
                    default_value = request.FILES['default'].name
                    cleaned_default = meta_field.clean_value(default_value)

                    if hasattr(settings, 'METAMODEL'):
                        path = os.path.join(
                            settings.METAMODEL.get('MEDIA_PATH', ''),
                            cleaned_default)
                    else:
                        path = cleaned_default

                    cleaned_default = default_storage.save(
                        path, request.FILES['default'])
                else:
                    default_value = request.POST.get('default')
                    cleaned_default = meta_field.clean_value(default_value)

                meta_field.save(default=cleaned_default)
            else:
                meta_field.save()

            return HttpResponseRedirect(
                reverse('metamodel_model_meta', kwargs={'pk': meta_model.pk}))

        self.object = meta_model
        context = self.get_context_data(**kwargs)
        context['form'] = form
        return self.render_to_response(context)
Пример #17
0
 def is_model_primitive(self):
     primitive_models_dict = MetaModel.get_primitive_models_dict()
     return self.model_id in primitive_models_dict