예제 #1
0
    def bind(self, model=None, session=None, data=None):
        """
        Return a copy of this FieldSet or Grid, bound to the given
        `model`, `session`, and `data`. The parameters to this method are the
        same as in the constructor.

        Often you will create and `configure` a FieldSet or Grid at application
        startup, then `bind` specific instances to it for actual editing or display.
        """
        if not (model or session or data):
            raise Exception('must specify at least one of {model, session, data}')
        if not model:
            if not self.model:
                raise Exception('model must be specified when none is already set')
            model = fields._pk(self.model) is None and type(self.model) or self.model
        # copy.copy causes a stacktrace on python 2.5.2/OSX + pylons.  unable to reproduce w/ simpler sample.
        mr = object.__new__(self.__class__)
        mr.__dict__ = dict(self.__dict__)
        # two steps so bind's error checking can work
        ModelRenderer.rebind(mr, model, session, data)
        mr._fields = OrderedDict([(key, renderer.bind(mr)) for key, renderer in self._fields.iteritems()])
        if self._render_fields:
            mr._render_fields = OrderedDict([(field.key, field) for field in
                                             [field.bind(mr) for field in self._render_fields.itervalues()]])
        return mr
예제 #2
0
 def render(self, **kwargs):
     if fields._pk(self.model) != self._bound_pk and self.data is not None:
         msg = ("Primary key of model has changed since binding, "
                "probably due to sync()ing a new instance (from %r to %r). "
                "You can solve this by either binding to a model "
                "with the original primary key again, or by binding data to None.")
         raise exceptions.PkError(msg % (self._bound_pk, fields._pk(self.model)))
     engine = self.engine or config.engine
     if self._render or self._render_readonly:
         warnings.warn(DeprecationWarning('_render and _render_readonly are deprecated and will be removed in 1.5. Use a TemplateEngine instead'))
     if self.readonly:
         if self._render_readonly is not None:
             engine._update_args(kwargs)
             return self._render_readonly(fieldset=self, **kwargs)
         return engine('fieldset_readonly', fieldset=self, **kwargs)
     if self._render is not None:
         engine._update_args(kwargs)
         return self._render(fieldset=self, **kwargs)
     return engine('fieldset', fieldset=self, **kwargs)
예제 #3
0
    def rebind(self, model=None, session=None, data=None):
        """
        Like `bind`, but acts on this instance.  No return value.
        Not all parameters are treated the same; specifically, what happens if they are NOT specified is different:
           * if `model` is not specified, the old model is used
           * if `session` is not specified, FA tries to re-guess session from the model
           * if data is not specified, it is rebound to None.
        """
        original_model = model
        if model:

            if isinstance(model, type):
                try:
                    model = model()
                except Exception, e:
                    model_error = str(e)
                    msg = ("%s appears to be a class, not an instance, but "
                           "FormAlchemy cannot instantiate it. "
                           "(Make sure all constructor parameters are "
                           "optional!). The error was:\n%s")
                    raise Exception(msg % (model, model_error))

                # take object out of session, if present
                try:
                    _obj_session = object_session(model)
                except AttributeError:
                    pass # non-SA object; doesn't need session
                else:
                    if _obj_session:
                        _obj_session.expunge(model)
            else:
                try:
                    session_ = object_session(model)
                except:
                    # non SA class
                    if fields._pk(model) is None:
                        error = ('Mapped instances to be bound must either have '
                                'a primary key set or not be in a Session.  When '
                                'creating a new object, bind the class instead '
                                '[i.e., bind(User), not bind(User())]')
                        raise Exception(error)
                else:
                    if session_:
                        # for instances of mapped classes, require that the instance
                        # have a PK already
                        try:
                            class_mapper(type(model))
                        except:
                            pass
                        else:
                            if fields._pk(model) is None:
                                error = ('Mapped instances to be bound must either have '
                                        'a primary key set or not be in a Session.  When '
                                        'creating a new object, bind the class instead '
                                        '[i.e., bind(User), not bind(User())]')
                                raise Exception(error)
            if (self.model and type(self.model) != type(model) and
                not issubclass(model.__class__, self._original_cls)):
                raise ValueError('You can only bind to another object of the same type or subclass you originally bound to (%s), not %s' % (type(self.model), type(model)))
            self.model = model
            self._bound_pk = fields._pk(model)