Exemple #1
0
def contribute_inline(model, form_class, inline_models):
    # Contribute columns
    for p in inline_models:
        # Figure out settings
        if isinstance(p, tuple):
            info = InlineFormAdmin(p[0], **p[1])
        elif isinstance(p, InlineFormAdmin):
            info = p
        elif isinstance(p, BaseModel):
            info = InlineFormAdmin(p)
        else:
            raise Exception('Unknown inline model admin: %s' % repr(p))

        # Find property from target model to current model
        reverse_field = None

        for field in info.model._meta.get_fields():
            field_type = type(field)

            if field_type == ForeignKeyField:
                if field.to == model:
                    reverse_field = field
                    break
        else:
            raise Exception('Cannot find reverse relation for model %s' %
                            info.model)

        # Remove reverse property from the list
        ignore = [reverse_field.name]

        if info.excluded_form_columns:
            exclude = ignore + info.excluded_form_columns
        else:
            exclude = ignore

        # Create field
        converter = CustomModelConverter()
        child_form = model_form(info.model,
                                base_class=form.BaseForm,
                                only=info.form_columns,
                                exclude=exclude,
                                field_args=info.form_args,
                                allow_pk=True,
                                converter=converter)

        prop_name = 'fa_%s' % model.__name__

        setattr(
            form_class, prop_name,
            InlineModelFormList(child_form,
                                info.model,
                                reverse_field.name,
                                label=info.model.__name__))

        setattr(field.to, prop_name, property(lambda self: self.id))

    return form_class
Exemple #2
0
    def get_info(self, p):
        info = super(InlineModelConverter, self).get_info(p)

        if info is None:
            if isinstance(p, BaseModel):
                info = InlineFormAdmin(p)
            else:
                model = getattr(p, 'model', None)
                if model is None:
                    raise Exception('Unknown inline model admin: %s' % repr(p))

                attrs = dict()

                for attr in dir(p):
                    if not attr.startswith('_') and attr != model:
                        attrs[attr] = getattr(p, attr)

                info = InlineFormAdmin(model, **attrs)

        return info
Exemple #3
0
    def get_info(self, p):
        info = super(InlineModelConverter, self).get_info(p)

        if info is None:
            if isinstance(p, BaseModel):
                info = InlineFormAdmin(p)
            else:
                model = getattr(p, 'model', None)
                if model is None:
                    raise Exception('Unknown inline model admin: %s' % repr(p))

                attrs = dict()

                for attr in dir(p):
                    if not attr.startswith('_') and attr != 'model':
                        attrs[attr] = getattr(p, attr)

                info = InlineFormAdmin(model, **attrs)

        # Resolve AJAX FKs
        info._form_ajax_refs = self.process_ajax_refs(info)

        return info
Exemple #4
0
    def get_info(self, p):
        info = super(InlineModelConverter, self).get_info(p)

        # Special case for model instances
        if info is None:
            if hasattr(p, '_sa_class_manager'):
                return InlineFormAdmin(p)
            else:
                model = getattr(p, 'model', None)

                if model is None:
                    raise Exception('Unknown inline model admin: %s' % repr(p))

                attrs = dict()
                for attr in dir(p):
                    if not attr.startswith('_') and attr != 'model':
                        attrs[attr] = getattr(p, attr)

                return InlineFormAdmin(model, **attrs)

            info = InlineFormAdmin(model, **attrs)

        return info
Exemple #5
0
def contribute_inline(session, model, form_class, inline_models):
    """
        Generate form fields for inline forms and contribute them to
        the `form_class`

        :param session:
            SQLAlchemy session
        :param model:
            Model class
        :param form_class:
            Form to add properties to
        :param inline_models:
            List of inline model definitions. Can be one of:

             - ``tuple``, first value is related model instance,
             second is dictionary with options
             - ``InlineFormAdmin`` instance
             - Model class

        :return:
            Form class
    """

    # Get mapper
    mapper = model._sa_class_manager.mapper

    # Contribute columns
    for p in inline_models:
        # Figure out settings
        if isinstance(p, tuple):
            info = InlineFormAdmin(p[0], **p[1])
        elif isinstance(p, InlineFormAdmin):
            info = p
        elif hasattr(p, '_sa_class_manager'):
            info = InlineFormAdmin(p)
        else:
            raise Exception('Unknown inline model admin: %s' % repr(p))

        # Find property from target model to current model
        target_mapper = info.model._sa_class_manager.mapper

        reverse_prop = None

        for prop in target_mapper.iterate_properties:
            if hasattr(prop,
                       'direction') and prop.direction.name == 'MANYTOONE':
                if prop.mapper.class_ == model:
                    reverse_prop = prop
                    break
        else:
            raise Exception('Cannot find reverse relation for model %s' %
                            info.model)

        # Find forward property
        forward_prop = None

        for prop in mapper.iterate_properties:
            if hasattr(prop,
                       'direction') and prop.direction.name == 'ONETOMANY':
                if prop.mapper.class_ == target_mapper.class_:
                    forward_prop = prop
                    break
        else:
            raise Exception('Cannot find forward relation for model %s' %
                            info.model)

        # Remove reverse property from the list
        ignore = [reverse_prop.key]

        if info.excluded_form_columns:
            exclude = ignore + info.excluded_form_columns
        else:
            exclude = ignore

        # Create field
        converter = AdminModelConverter(session, info)
        child_form = get_form(info.model,
                              converter,
                              only=info.form_columns,
                              exclude=exclude,
                              field_args=info.form_args,
                              hidden_pk=True)

        setattr(
            form_class, forward_prop.key,
            InlineModelFormList(child_form, session, info.model,
                                forward_prop.key))

    return form_class