Пример #1
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 'request' not in kwargs:
         kwargs['request'] = self._request
     if self.readonly:
         template = 'fieldset_readonly'
     else:
         template = 'fieldset'
     return engine(template, fieldset=self, **kwargs)
Пример #2
0
    def update(self):
        request = self.request
        id = request.model_id
        fs = self.get_fieldset(suffix="Edit", id=id)

        event = events.BeforeRenderEvent(self.request.model_instance, self.request, fs=fs)
        alsoProvides(event, events.IBeforeEditRenderEvent)
        zope.component.event.objectEventNotify(event)

        if request.format == "json" and request.method == "PUT":
            data = json.load(request.body_file)
        elif request.content_type == "application/json":
            data = json.load(request.body_file)
        else:
            data = request.POST

        with_prefix = True
        if request.format == "json":
            with_prefix = bool(request.params.get("with_prefix"))

        fs = fs.bind(request=request, with_prefix=with_prefix)
        if self.validate(fs):
            fs.sync()
            self.sync(fs, id)
            self.session.flush()
            if request.format in ("html", "xhr"):
                if request.is_xhr or request.format == "xhr":
                    return Response(content_type="text/plain")
                return exc.HTTPFound(location=request.fa_url(request.model_name, _pk(fs.model)))
            else:
                return self.render(fs=fs, status=0)
        if request.format == "html":
            return self.render(fs=fs, id=id)
        else:
            return self.render(fs=fs, status=1)
Пример #3
0
 def list(self, modelname, format='html'):
     """List instances of a model type"""
     S = self.Session()
     grid = self._model_grids[modelname]
     query = S.query(grid.model.__class__)
     page = Page(query,
                 page=int(request.GET.get('page', '1')),
                 **self._paginate)
     if format == 'json':
         values = []
         for item in page:
             pk = _pk(item)
             values.append((pk, url('view_model', pk)))
         return self.render_json(records=dict(values),
                                 page_count=page.page_count,
                                 page=page.page)
     grid = grid.bind(instances=page, session=None)
     clsnames = [
         f.relation_type().__name__ for f in grid._fields.itervalues()
         if f.is_relation
     ]
     return self._engine('admin_list',
                         c=c,
                         grid=grid,
                         page=page,
                         clsnames=clsnames,
                         modelname=modelname,
                         custom_css=self._custom_css,
                         custom_js=self._custom_js)
Пример #4
0
    def listing(self, *args, **kwargs):
        request = self.request
        if request.format != 'json':
            return Base.listing(self, *args, **kwargs)
        page = self.get_page(**kwargs)
        fs = self.get_grid()
        fs = fs.bind(instances=page, request=self.request)
        columns = []
        fields = []
        total = 0
        for field in fs.render_fields.values():
            type = field.type.__class__.__name__.lower()
            columns.append(dict(
                      dataIndex=field.name, header=field.label(),
                      editor=dict(xtype=self.xtypes.get(type, '%sfield' % type)),
                      width=160, fixed=False
                   ))
            fields.append(dict(name=field.name, type=self.types.get(type, type)))

        values = []
        for item in page:
            total = total+1
            pk = _pk(item)
            fs._set_active(item)
            value = dict(id=pk,
                         absolute_url=request.fa_url(request.model_name, request.format, pk))
            value.update(fs.to_dict(with_prefix=bool(request.params.get('with_prefix'))))
            values.append(value)

        data = dict(columns=columns, metaData=dict(fields=fields, root='records', id='id'), records=values, success=True, total=total)
        return Response(self.encoder.encode(data),
                        content_type='application/json')
Пример #5
0
 def edit_link():
     return lambda item: '''
     <form action="%(url)s" method="GET" class="ui-grid-icon ui-widget-header ui-corner-all">
     <input type="submit" class="ui-grid-icon ui-icon ui-icon-pencil" title="%(label)s" value="%(label)s" />
     </form>
     ''' % dict(url=model_url('edit_%s' % self.member_name, id=_pk(item)),
                 label=get_translator()('edit'))
Пример #6
0
 def listing(self, **kwargs):
     """listing page"""
     page = self.get_page()
     fs = self.get_grid()
     fs = fs.bind(instances=page)
     fs.readonly = True
     if self.request.format == 'json':
         values = []
         request = self.request
         for item in page:
             pk = _pk(item)
             fs._set_active(item)
             value = dict(id=pk,
                          item_url=self.route_url(request.model_name, pk))
             if 'jqgrid' in request.GET:
                 fields = [_stringify(field.render_readonly()) for field in fs.render_fields.values()]
                 value['cell'] = [pk] + fields
             else:
                 value.update(dict([(field.key, field.model_value) for field in fs.render_fields.values()]))
             values.append(value)
         return self.render_json_format(rows=values,
                                        records=len(values),
                                        total=page.page_count,
                                        page=page.page)
     if 'pager' not in kwargs:
         pager = page.pager(**self.pager_args)
     else:
         pager = kwargs.pop('pager')
     return self.render_grid(fs=fs, id=None, pager=pager)
Пример #7
0
 def bind(self, model=None, session=None, data=None, request=None):
     """Bind to an instance"""
     self._request = request
     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 self._original_cls 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
     mr.rebind(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
Пример #8
0
 def __init__(self, model, **kwargs):
     BaseFieldSet.__init__(self, model, **kwargs)
     if model is not None and isinstance(model, schema.Document):
         BaseFieldSet.rebind(self, model.__class__, data=kwargs.get('data', None))
         self.doc = model.__class__
         self.model = model
         self._bound_pk = fields._pk(model)
     else:
         BaseFieldSet.rebind(self, model, data=kwargs.get('data', None))
         self.doc = model
     values = self.doc._properties.values()
     values.sort(lambda a, b: cmp(a.creation_counter, b.creation_counter))
     for v in values:
         if getattr(v, 'name'):
             k = v.name
             sch = None
             if isinstance(v, schema.SchemaListProperty):
                 t = fatypes.List
                 sch = v._schema
             elif isinstance(v, schema.SchemaProperty):
                 t = fatypes.String
                 sch = v._schema
             else:
                 try:
                     t = getattr(fatypes, v.__class__.__name__.replace('Property',''))
                 except AttributeError:
                     raise NotImplementedError('%s is not mapped to a type for field %s (%s)' % (v.__class__, k, v.__class__.__name__))
             self.append(Field(name=k, type=t, schema=sch))
             if v.required:
                 self._fields[k].validators.append(validators.required)
Пример #9
0
 def update(self, **kwargs):
     """REST api"""
     request = self.request
     S = self.Session()
     id = request.model_id
     fs = self.get_fieldset(id)
     if not request.POST:
         raise ValueError(request.POST)
     fs = fs.bind(data=request.POST)
     if fs.validate():
         fs.sync()
         self.sync(fs, id)
         S.flush()
         if request.format == 'html':
             if request.is_xhr:
                 response.content_type = 'text/plain'
                 return ''
             return exc.HTTPFound(
                     location=self.route_url(request.model_name, _pk(fs.model)))
         else:
             return self.render(fs=fs, status=0)
     if request.format == 'html':
         return self.render(fs=fs, action='edit', id=id)
     else:
         return self.render(fs=fs, status=1)
Пример #10
0
 def edit_link():
     return lambda item: '''
     <form action="%(url)s" method="GET" class="ui-grid-icon ui-widget-header ui-corner-all">
     <input type="submit" class="ui-grid-icon ui-icon ui-icon-pencil" title="%(label)s" value="%(label)s" />
     </form>
     ''' % dict(url=self.request.fa_url(self.request.model_name, _pk(item), 'edit'),
                 label=get_translator(request=self.request)('edit'))
Пример #11
0
    def update(self):
        request = self.request
        id = request.model_id
        fs = self.get_fieldset(suffix='Edit', id=id)

        event = events.BeforeRenderEvent(self.request.model_instance, self.request, fs=fs)
        alsoProvides(event, events.IBeforeEditRenderEvent)
        zope.component.event.objectEventNotify(event)

        fs = fs.bind(request=request)
        if self.validate(fs):
            fs.sync()
            self.sync(fs, id)
            self.session.flush()
            if request.format in ('html', 'xhr'):
                if request.is_xhr or request.format == 'xhr':
                    return Response(content_type='text/plain')
                return exc.HTTPFound(
                        location=request.fa_url(request.model_name, _pk(fs.model)))
            else:
                return self.render(fs=fs, status=0)
        if request.format == 'html':
            return self.render(fs=fs, id=id)
        else:
            return self.render(fs=fs, status=1)
Пример #12
0
 def delete_link():
     return lambda item: '''
     <form action="%(url)s" method="POST" class="ui-grid-icon ui-state-error ui-corner-all">
     <input type="submit" class="ui-icon ui-icon-circle-close" title="%(label)s" value="%(label)s" />
     </form>
     ''' % dict(url=self.request.fa_url(self.request.model_name, _pk(item), 'delete'),
                label=get_translator(request=self.request)('delete'))
Пример #13
0
 def edit_link():
     return lambda item: '''
     <form action="%(url)s" method="GET" class="ui-grid-icon ui-widget-header ui-corner-all">
     <input type="submit" class="ui-grid-icon ui-icon ui-icon-pencil" title="%(label)s" value="%(label)s" />
     </form>
     ''' % dict(url=model_url('edit_%s' % self.member_name, id=_pk(item)),
                 label=get_translator()('edit'))
Пример #14
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
Пример #15
0
 def __init__(self, model, **kwargs):
     BaseFieldSet.__init__(self, model, **kwargs)
     if model is not None and isinstance(model, schema.Document):
         BaseFieldSet.rebind(self, model.__class__, data=kwargs.get('data', None))
         self.doc = model.__class__
         self.model = model
         self._bound_pk = fields._pk(model)
     else:
         BaseFieldSet.rebind(self, model, data=kwargs.get('data', None))
         self.doc = model
     values = self.doc._properties.values()
     values.sort(lambda a, b: cmp(a.creation_counter, b.creation_counter))
     for v in values:
         if getattr(v, 'name'):
             k = v.name
             sch = None
             if isinstance(v, schema.SchemaListProperty):
                 t = fatypes.List
                 sch = v._schema
             elif isinstance(v, schema.SchemaProperty):
                 t = fatypes.String
                 sch = v._schema
             else:
                 try:
                     t = getattr(fatypes, v.__class__.__name__.replace('Property',''))
                 except AttributeError:
                     raise NotImplementedError('%s is not mapped to a type for field %s (%s)' % (v.__class__, k, v.__class__.__name__))
             self.append(Field(name=k, type=t, schema=sch))
             if v.required:
                 self._fields[k].validators.append(validators.required)
Пример #16
0
 def index(self, format='html', **kwargs):
     """REST api"""
     page = self.get_page()
     fs = self.get_grid()
     fs = fs.bind(instances=page)
     fs.readonly = True
     if format == 'json':
         values = []
         for item in page:
             pk = _pk(item)
             fs._set_active(item)
             value = dict(id=pk,
                          item_url=model_url(self.member_name, id=pk))
             if 'jqgrid' in request.GET:
                 fields = [_stringify(field.render_readonly()) for field in fs.render_fields.values()]
                 value['cell'] = [pk] + fields
             else:
                 value.update(dict([(field.key, field.model_value) for field in fs.render_fields.values()]))
             values.append(value)
         return self.render_json_format(rows=values,
                                        records=len(values),
                                        total=page.page_count,
                                        page=page.page)
     if 'pager' not in kwargs:
         pager = page.pager(**self.pager_args)
     else:
         pager = kwargs.pop('pager')
     return self.render_grid(format=format, fs=fs, id=None, pager=pager)
Пример #17
0
    def listing(self, **kwargs):
        """listing page"""
        page = self.get_page(**kwargs)
        fs = self.get_grid()
        fs = fs.bind(instances=page, request=self.request)
        fs.readonly = True

        event = events.BeforeRenderEvent(self.request.model_class(), self.request, fs=fs, page=page)
        alsoProvides(event, events.IBeforeListingRenderEvent)
        zope.component.event.objectEventNotify(event)

        if self.request.format == 'json':
            values = []
            request = self.request
            for item in page:
                pk = _pk(item)
                fs._set_active(item)
                value = dict(id=pk,
                             absolute_url=request.fa_url(request.model_name, pk))
                if 'jqgrid' in request.GET:
                    fields = [_stringify(field.render_readonly()) for field in fs.render_fields.values()]
                    value['cell'] = [pk] + fields
                else:
                    value.update(fs.to_dict(with_prefix=bool(request.params.get('with_prefix'))))
                values.append(value)
            return self.render_json_format(rows=values,
                                           records=len(values),
                                           total=page.page_count,
                                           page=page.page)
        if 'pager' not in kwargs:
            pager = page.pager(**self.pager_args)
        else:
            pager = kwargs.pop('pager')
        return self.render_grid(fs=fs, id=None, pager=pager)
Пример #18
0
 def delete_link():
     return lambda item: '''
     <form action="%(url)s" method="POST" class="ui-grid-icon ui-state-error ui-corner-all">
     <input type="submit" class="ui-icon ui-icon-circle-close" title="%(label)s" value="%(label)s" />
     <input type="hidden" name="_method" value="DELETE" />
     </form>
     ''' % dict(url=model_url(self.member_name, id=_pk(item)),
                label=get_translator()('delete'))
Пример #19
0
 def delete_link():
     return lambda item: '''<form action="%(url)sdelete/%(id)s" method="POST">
                             <input type="submit" class="icon delete" title="%(label)s" value="" />
                             <input type="hidden" name="_method" value="DELETE" />
                             </form>
                         ''' % dict(
                                 url=model_URL, id=_pk(item),
                                 label=get_translator().gettext('delete'))
Пример #20
0
 def edit_link():
     return lambda item: '''
     <form action="%(url)s" method="GET" class="ui-grid-icon ui-widget-header ui-corner-all">
     <input type="submit" class="ui-grid-icon ui-icon ui-icon-pencil" title="%(label)s" value="%(label)s" />
     </form>
     ''' % dict(url=self.request.fa_url(self.request.model_name,
                                        _pk(item), 'edit'),
                label=get_translator(request=self.request)('edit'))
Пример #21
0
 def delete_link():
     return lambda item: '''
     <form action="%(url)s" method="POST" class="ui-grid-icon ui-state-error ui-corner-all">
     <input type="submit" class="ui-icon ui-icon-circle-close" title="%(label)s" value="%(label)s" />
     <input type="hidden" name="_method" value="DELETE" />
     </form>
     ''' % dict(url=model_url(self.member_name, id=_pk(item)),
                label=get_translator()('delete'))
Пример #22
0
 def delete_link():
     return lambda item: '''
     <form action="%(url)s" method="POST" class="ui-grid-icon ui-state-error ui-corner-all">
     <input type="submit" class="ui-icon ui-icon-circle-close" title="%(label)s" value="%(label)s" />
     </form>
     ''' % dict(url=self.request.fa_url(self.request.model_name,
                                        _pk(item), 'delete'),
                label=get_translator(request=self.request)
                ('delete'))
Пример #23
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 'request' not in kwargs:
         kwargs['request'] = self._request
     if self.readonly:
         template = 'fieldset_readonly'
     else:
         template = 'fieldset'
     return engine(template, fieldset=self, **kwargs)
Пример #24
0
 def delete_link():
     model_url = url('models', modelname=modelname)
     return lambda item: '''<form action="%(url)s/%(id)s" method="POST">
                             <input type="submit" class="icon delete" title="%(label)s" value="" />
                             <input type="hidden" name="_method" value="DELETE" />
                             </form>
                         ''' % dict(url=model_url,
                                    id=_pk(item),
                                    label=get_translator().gettext(
                                        'delete'))
Пример #25
0
 def delete(self, modelname, id):
     """Delete an instance of the given model type"""
     F_ = get_translator().gettext
     fs = self._model_fieldsets[modelname]
     S = self.Session()
     instance = S.query(fs.model.__class__).get(id)
     key = _pk(instance)
     S.delete(instance)
     S.commit()
     message = F_(_("Deleted %s %s")) % (modelname.encode("utf-8", "ignore"), key)
     flash(message)
     redirect_to(controller=self._name, modelname=modelname, action="list", id=None)
Пример #26
0
 def render(self, *args, **kwargs):
     html = super(Renderer, self).render(*args, **kwargs)
     fk_class = self.field.relation_type()
     model_name = fk_class.__name__
     try:
         field_url = '%s.xhr?field=%s' % (model_url('model', id=fields._pk(self.field.model)), self.field.key)
     except GenerationException:
         field_url = '%s.xhr?field=%s' % (model_url('new_model'), self.field.key)
     new_url = '%s.xhr' % model_url('new_model', model_name=model_name)
     html += literal('<button class="new_relation_item" alt="%s" href="%s">New %s</button>' % (
                                         field_url, new_url, model_name))
     return html
Пример #27
0
 def render_json(self, fs=None, **kwargs):
     response.content_type = 'text/javascript'
     if fs:
         fields = dict([(field.key, field.model_value) for field in fs.render_fields.values()])
         data = dict(fields=fields)
         pk = _pk(fs.model)
         if pk:
             data['url'] = url('view_model', modelname=fs.model.__class__.__name__, id=pk)
     else:
         data = {}
     data.update(kwargs)
     return json.dumps(data)
Пример #28
0
    def render_readonly(self, options=None, **kwargs):
        value = self.raw_value
        if value is None:
            return ''

        if not isinstance(value, list):
            if self.request.has_permission('view', value):
                return h.content_tag('a',
                    self.stringify_value(value, as_html=True),
                    href=self.request.fa_url(value.__class__.__name__, fields._pk(value)))
            else:
                return h.content_tag('span', self.stringify_value(value, as_html=True))
        else:
            html = []
            for item in value:
                if self.request.has_permission('view', item):
                    html.append(h.content_tag('a',
                                self.stringify_value(item, as_html=True),
                                href=self.request.fa_url(item.__class__.__name__, fields._pk(item))))
                else:
                    html.append(h.content_tag('span', self.stringify_value(item, as_html=True)))
            return h.literal(',&nbsp;').join(html)
Пример #29
0
 def render(self, *args, **kwargs):
     html = super(Renderer, self).render(*args, **kwargs)
     pk = fields._pk(self.field.model)
     model_name = self.field.parent.model.__class__.__name__
     if pk:
         field_url = '#root_url/%s/xhr/%s?field=%s' % (model_name, pk, self.field.key)
     else:
         field_url = '#root_url/%s/xhr?field=%s' % (model_name, self.field.key)
     fk_class = self.field.relation_type()
     model_name = fk_class.__name__
     new_url = '#root_url/%s/xhr/new' % model_name
     html += literal('<button class="new_relation_item" alt="%s" href="%s">New %s</button>' % (
                                         field_url, new_url, model_name))
     return html
Пример #30
0
 def render_json_format(self, fs=None, **kwargs):
     request = self.request
     request.override_renderer = "json"
     if fs is not None:
         data = fs.to_dict(with_prefix=request.params.get("with_prefix", False))
         pk = _pk(fs.model)
         if pk:
             if "id" not in data:
                 data["id"] = pk
             data["absolute_url"] = request.fa_url(request.model_name, "json", pk)
     else:
         data = {}
     data.update(kwargs)
     return data
Пример #31
0
 def render_json_format(self, fs=None, **kwargs):
     request = self.request
     request.override_renderer = 'json'
     if fs is not None:
         data = fs.to_dict(with_prefix=request.params.get('with_prefix', False))
         pk = _pk(fs.model)
         if pk:
             if 'id' not in data:
                 data['id'] = pk
             data['absolute_url'] = request.fa_url(request.model_name, 'json', pk)
     else:
         data = {}
     data.update(kwargs)
     return data
Пример #32
0
 def render(self, *args, **kwargs):
     html = super(Renderer, self).render(*args, **kwargs)
     pk = fields._pk(self.field.model)
     model_name = self.field.parent.model.__class__.__name__
     request = self.request
     if pk:
         field_url = request.fa_url(model_name, 'xhr', pk, field=self.field.key)
     else:
         field_url = request.fa_url(model_name, 'xhr', field=self.field.key)
     fk_class = self.field.relation_type()
     model_name = fk_class.__name__
     new_url = request.fa_url(model_name, 'xhr', 'new')
     html += literal('<button class="new_relation_item" alt="%s" href="%s">New %s</button>' % (
                                         field_url, new_url, model_name))
     return html
Пример #33
0
 def render_json_format(self, fs=None, **kwargs):
     response.content_type = "text/javascript"
     if fs:
         try:
             fields = fs.jsonify()
         except AttributeError:
             fields = dict([(field.renderer.name, field.model_value) for field in fs.render_fields.values()])
         data = dict(fields=fields)
         pk = _pk(fs.model)
         if pk:
             data["item_url"] = model_url(self.member_name, id=pk)
     else:
         data = {}
     data.update(kwargs)
     return json.dumps(data)
Пример #34
0
 def render(self, *args, **kwargs):
     html = super(Renderer, self).render(*args, **kwargs)
     fk_class = self.field.relation_type()
     model_name = fk_class.__name__
     try:
         field_url = '%s.xhr?field=%s' % (model_url(
             'model', id=fields._pk(self.field.model)), self.field.key)
     except GenerationException:
         field_url = '%s.xhr?field=%s' % (model_url('new_model'),
                                          self.field.key)
     new_url = '%s.xhr' % model_url('new_model', model_name=model_name)
     html += literal(
         '<button class="new_relation_item" alt="%s" href="%s">New %s</button>'
         % (field_url, new_url, model_name))
     return html
Пример #35
0
 def render_json(self, fs=None, **kwargs):
     response.content_type = 'text/javascript'
     if fs:
         fields = dict([(field.key, field.model_value)
                        for field in fs.render_fields.values()])
         data = dict(fields=fields)
         pk = _pk(fs.model)
         if pk:
             data['url'] = url('view_model',
                               modelname=fs.model.__class__.__name__,
                               id=pk)
     else:
         data = {}
     data.update(kwargs)
     return json.dumps(data)
Пример #36
0
 def render_json_format(self, fs=None, **kwargs):
     response.content_type = 'text/javascript'
     if fs:
         try:
             fields = fs.jsonify()
         except AttributeError:
             fields = dict([(field.renderer.name, field.model_value) for field in fs.render_fields.values()])
         data = dict(fields=fields)
         pk = _pk(fs.model)
         if pk:
             data['item_url'] = model_url(self.member_name, id=pk)
     else:
         data = {}
     data.update(kwargs)
     return json.dumps(data)
Пример #37
0
 def render(self, *args, **kwargs):
     html = super(Renderer, self).render(*args, **kwargs)
     pk = fields._pk(self.field.model)
     model_name = self.field.parent.model.__class__.__name__
     request = self.request
     if pk:
         field_url = request.fa_url(model_name, 'xhr', pk, field=self.field.key)
     else:
         field_url = request.fa_url(model_name, 'xhr', field=self.field.key)
     fk_class = self.field.relation_type()
     model_name = fk_class.__name__
     new_url = request.fa_url(model_name, 'xhr', 'new')
     html += literal('<button class="new_relation_item" alt="%s" href="%s">New %s</button>' % (
                                         field_url, new_url, model_name))
     return html
Пример #38
0
 def render_json_format(self, fs=None, **kwargs):
     request = self.request
     request.override_renderer = 'json'
     if fs:
         try:
             fields = fs.jsonify()
         except AttributeError:
             fields = dict([(field.renderer.name, field.model_value) for field in fs.render_fields.values()])
         data = dict(fields=fields)
         pk = _pk(fs.model)
         if pk:
             data['item_url'] = request.route_url('fa_admin', traverse='%s/json/%s' % (self.model_name, pk))
     else:
         data = {}
     data.update(kwargs)
     return data
Пример #39
0
 def render_json_format(self, fs=None, **kwargs):
     request = self.request
     request.override_renderer = 'json'
     if fs is not None:
         data = fs.to_dict(
             with_prefix=request.params.get('with_prefix', False))
         pk = _pk(fs.model)
         if pk:
             if 'id' not in data:
                 data['id'] = pk
             data['absolute_url'] = request.fa_url(request.model_name,
                                                   'json', pk)
     else:
         data = {}
     data.update(kwargs)
     return data
Пример #40
0
    def delete(self, modelname, id, format='html'):
        """Delete an instance of the given model type"""
        F_ = get_translator().gettext
        fs = self._model_fieldsets[modelname]
        S = self.Session()
        instance = S.query(fs.model.__class__).get(id)
        key = _pk(instance)
        S.delete(instance)
        S.commit()

        if format == 'html':
            message = F_(_('Deleted %s %s')) % (modelname.encode(
                'utf-8', 'ignore'), key)
            flash(message)
            redirect(url('models', modelname=modelname))
        else:
            return self.render_json(status=0)
Пример #41
0
    def delete(self, modelname, id, format='html'):
        """Delete an instance of the given model type"""
        F_ = get_translator().gettext
        fs = self._model_fieldsets[modelname]
        S = self.Session()
        instance = S.query(fs.model.__class__).get(id)
        key = _pk(instance)
        S.delete(instance)
        S.commit()

        if format == 'html':
            message = F_(_('Deleted %s %s')) % (modelname.encode('utf-8', 'ignore'),
                                                key)
            flash(message)
            redirect(url('models', modelname=modelname))
        else:
            return self.render_json(status=0)
Пример #42
0
 def rebind(self, model, session=None, data=None):
     if model is not self.iface:
         if model and not self.iface.providedBy(model):
             if getattr(model, '__implemented__', None) is not None:
                 raise ValueError('%r does not provide %r' % (model, self.iface))
             model = self.gen_model(model)
     self.model = model
     self._bound_pk = fields._pk(model)
     if data is None:
         self.data = None
     elif hasattr(data, 'getall') and hasattr(data, 'getone'):
         self.data = data
     else:
         try:
             self.data = SimpleMultiDict(data)
         except:
             raise Exception('unsupported data object %s. currently only dicts and Paste multidicts are supported' % self.data)
Пример #43
0
 def render(self, *args, **kwargs):
     html = super(Renderer, self).render(*args, **kwargs)
     pk = fields._pk(self.field.model)
     model_name = self.field.parent.model.__class__.__name__
     if pk:
         field_url = '#root_url/%s/xhr/%s?field=%s' % (model_name, pk,
                                                       self.field.key)
     else:
         field_url = '#root_url/%s/xhr?field=%s' % (model_name,
                                                    self.field.key)
     fk_class = self.field.relation_type()
     model_name = fk_class.__name__
     new_url = '#root_url/%s/xhr/new' % model_name
     html += literal(
         '<button class="new_relation_item" alt="%s" href="%s">New %s</button>'
         % (field_url, new_url, model_name))
     return html
Пример #44
0
 def bind(self, model, session=None, data=None):
     """Bind to an instance"""
     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
     mr.rebind(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
Пример #45
0
    def bind(self,
             model=None,
             session=None,
             data=None,
             request=None,
             with_prefix=True):
        """
        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 is not None or session or data or request):
            raise Exception(
                'must specify at least one of {model, session, data, request}')

        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
        FieldSet.rebind(mr,
                        model,
                        session,
                        data,
                        request,
                        with_prefix=with_prefix)
        mr._fields = OrderedDict([(key, renderer.bind(mr))
                                  for key, renderer in self._fields.items()])
        if self._render_fields:
            mr._render_fields = OrderedDict([
                (field.key, field) for field in
                [field.bind(mr) for field in self._render_fields.values()]
            ])
        mr._request = request
        return mr
Пример #46
0
    def listing(self, **kwargs):
        """listing page"""
        page = self.get_page(**kwargs)
        fs = self.get_grid()
        fs = fs.bind(instances=page, request=self.request)
        fs.readonly = True

        event = events.BeforeRenderEvent(self.request.model_class(),
                                         self.request,
                                         fs=fs,
                                         page=page)
        alsoProvides(event, events.IBeforeListingRenderEvent)
        zope.component.event.objectEventNotify(event)

        if self.request.format == 'json':
            values = []
            request = self.request
            for item in page:
                pk = _pk(item)
                fs._set_active(item)
                value = dict(id=pk,
                             absolute_url=request.fa_url(
                                 request.model_name, pk))
                if 'jqgrid' in request.GET:
                    fields = [
                        _stringify(field.render_readonly())
                        for field in fs.render_fields.values()
                    ]
                    value['cell'] = [pk] + fields
                else:
                    value.update(
                        fs.to_dict(with_prefix=bool(
                            request.params.get('with_prefix'))))
                values.append(value)
            return self.render_json_format(rows=values,
                                           records=len(values),
                                           total=page.page_count,
                                           page=page.page)
        if 'pager' not in kwargs:
            pager = page.pager(**self.pager_args)
        else:
            pager = kwargs.pop('pager')
        return self.render_grid(fs=fs, id=None, pager=pager)
Пример #47
0
 def rebind(self, model, session=None, data=None):
     if model is not self.iface:
         if model and not self.iface.providedBy(model):
             if getattr(model, '__implemented__', None) is not None:
                 raise ValueError('%r does not provide %r' %
                                  (model, self.iface))
             model = self.gen_model(model)
     self.model = model
     self._bound_pk = fields._pk(model)
     if data is None:
         self.data = None
     elif hasattr(data, 'getall') and hasattr(data, 'getone'):
         self.data = data
     else:
         try:
             self.data = SimpleMultiDict(data)
         except:
             raise Exception(
                 'unsupported data object %s. currently only dicts and Paste multidicts are supported'
                 % self.data)
Пример #48
0
 def list(self, modelname, format='html'):
     """List instances of a model type"""
     S = self.Session()
     grid = self._model_grids[modelname]
     query = S.query(grid.model.__class__)
     page = Page(query, page=int(request.GET.get('page', '1')), **self._paginate)
     if format == 'json':
         values = []
         for item in page:
             pk = _pk(item)
             values.append((pk, url('view_model', pk)))
         return self.render_json(records=dict(values), page_count=page.page_count, page=page.page)
     grid = grid.bind(instances=page, session=None)
     clsnames = [f.relation_type().__name__ for f in grid._fields.itervalues() if f.is_relation]
     return self._engine('admin_list', c=c,
                         grid=grid,
                         page=page,
                         clsnames=clsnames,
                         modelname=modelname,
                         custom_css = self._custom_css,
                         custom_js = self._custom_js)
Пример #49
0
 def edit(self, modelname, id=None):
     """Edit (or create, if `id` is None) an instance of the given model type"""
     F_ = get_translator().gettext
     fs = self._model_fieldsets[modelname]
     S = self.Session()
     if id:
         instance = S.query(fs.model.__class__).get(id)
         c.fs = fs.bind(instance)
         title = "Edit"
     else:
         c.fs = fs.bind(fs.model.__class__, session=S)
         title = "New object"
     if request.method == "POST":
         c.fs = c.fs.bind(data=request.params)
         log.debug("saving %s w/ %s" % (c.fs.model.id, request.POST))
         if c.fs.validate():
             c.fs.sync()
             S.flush()
             if not id:
                 # needed if the object does not exist in db
                 if not object_session(c.fs.model):
                     S.save(c.fs.model)
                 message = _("Created %s %s")
             else:
                 S.refresh(c.fs.model)
                 message = _("Modified %s %s")
             S.commit()
             message = F_(message) % (modelname.encode("utf-8", "ignore"), _pk(c.fs.model))
             flash(message)
             redirect_to(modelname=modelname, action="list", id=None)
     return self._engine(
         "admin_edit",
         c=c,
         action=title,
         id=id,
         controller=self._name,
         modelname=modelname,
         custom_css=self._custom_css,
         custom_js=self._custom_js,
     )
Пример #50
0
    def update(self):
        request = self.request
        id = request.model_id
        fs = self.get_fieldset(suffix='Edit', id=id)

        event = events.BeforeRenderEvent(self.request.model_instance,
                                         self.request,
                                         fs=fs)
        alsoProvides(event, events.IBeforeEditRenderEvent)
        zope.component.event.objectEventNotify(event)

        if request.format == 'json' and request.method == 'PUT':
            data = json.load(request.body_file)
        elif request.content_type == 'application/json':
            data = json.load(request.body_file)
        else:
            data = request.POST

        with_prefix = True
        if request.format == 'json':
            with_prefix = bool(request.params.get('with_prefix'))

        fs = fs.bind(request=request, with_prefix=with_prefix)
        if self.validate(fs):
            fs.sync()
            self.sync(fs, id)
            self.session.flush()
            if request.format in ('html', 'xhr'):
                if request.is_xhr or request.format == 'xhr':
                    return Response(content_type='text/plain')
                return exc.HTTPFound(
                    location=request.fa_url(request.model_name, _pk(fs.model)))
            else:
                return self.render(fs=fs, status=0)
        if request.format == 'html':
            return self.render(fs=fs, id=id)
        else:
            return self.render(fs=fs, status=1)
Пример #51
0
 def rebind(self, model=None, session=None, data=None):
     if model is not None and model is not self.doc:
         if not isinstance(model, self.doc):
             try:
                 model = model()
             except Exception as e:
                 raise Exception('''%s appears to be a class, not an instance,
                         but FormAlchemy cannot instantiate it.  (Make sure
                         all constructor parameters are optional!) %r - %s''' % (
                         model, self.doc, e))
     else:
         model = self.doc()
     self.model = model
     self._bound_pk = fields._pk(model)
     if data is None:
         self.data = None
     elif hasattr(data, 'getall') and hasattr(data, 'getone'):
         self.data = data
     else:
         try:
             self.data = SimpleMultiDict(data)
         except:
             raise Exception('unsupported data object %s.  currently only dicts and Paste multidicts are supported' % self.data)
Пример #52
0
 def rebind(self, model=None, session=None, data=None):
     if model is not None and model is not self.doc:
         if not isinstance(model, self.doc):
             try:
                 model = model()
             except Exception as e:
                 raise Exception('''%s appears to be a class, not an instance,
                         but FormAlchemy cannot instantiate it.  (Make sure
                         all constructor parameters are optional!) %r - %s''' % (
                         model, self.doc, e))
     else:
         model = self.doc()
     self.model = model
     self._bound_pk = fields._pk(model)
     if data is None:
         self.data = None
     elif hasattr(data, 'getall') and hasattr(data, 'getone'):
         self.data = data
     else:
         try:
             self.data = SimpleMultiDict(data)
         except:
             raise Exception('unsupported data object %s.  currently only dicts and Paste multidicts are supported' % self.data)
Пример #53
0
    def edit(self, modelname, id=None, format='html'):
        """Edit (or create, if `id` is None) an instance of the given model type"""

        saved = 1

        if id and id.endswith('.json'):
            id = id[:-5]
            format = 'json'

        if request.method == 'POST' or format == 'json':
            if id:
                prefix = '%s-%s' % (modelname, id)
            else:
                prefix = '%s-' % modelname

            if request.method == 'PUT':
                items = json.load(request.body_file).items()
                request.method = 'POST'
            elif '_method' not in request.POST:
                items = request.POST.items()
                format = 'json'
            else:
                items = None

            if items:
                for k, v in items:
                    if not k.startswith(prefix):
                        if isinstance(v, list):
                            for val in v:
                                request.POST.add('%s-%s' % (prefix, k), val)
                        else:
                            request.POST.add('%s-%s' % (prefix, k), v)

        fs = self._model_fieldsets[modelname]
        S = self.Session()

        if id:
            instance = S.query(fs.model.__class__).get(id)
            assert instance, id
            title = 'Edit'
        else:
            instance = fs.model.__class__
            title = 'New object'

        if request.method == 'POST':
            F_ = get_translator().gettext
            c.fs = fs.bind(instance,
                           data=request.POST,
                           session=not id and S or None)
            if c.fs.validate():
                c.fs.sync()
                S.flush()
                if not id:
                    # needed if the object does not exist in db
                    if not object_session(c.fs.model):
                        S.add(c.fs.model)
                    message = _('Created %s %s')
                else:
                    S.refresh(c.fs.model)
                    message = _('Modified %s %s')
                S.commit()
                saved = 0

                if format == 'html':
                    message = F_(message) % (modelname.encode(
                        'utf-8', 'ignore'), _pk(c.fs.model))
                    flash(message)
                    redirect(url('models', modelname=modelname))
        else:
            c.fs = fs.bind(instance, session=not id and S or None)

        if format == 'html':
            return self._engine('admin_edit',
                                c=c,
                                action=title,
                                id=id,
                                modelname=modelname,
                                custom_css=self._custom_css,
                                custom_js=self._custom_js)
        else:
            return self.render_json(fs=c.fs, status=saved, model=modelname)
Пример #54
0
 def edit_link():
     model_url = url('models', modelname=modelname)
     return lambda item: '<a href="%(url)s/%(id)s" title="%(label)s" class="icon edit">%(label)s</a>' % dict(
         url=model_url,
         id=_pk(item),
         label=get_translator().gettext('edit'))
Пример #55
0
    def rebind(self,
               model=None,
               session=None,
               data=None,
               request=None,
               with_prefix=True):
        """
        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
        * if `request` is specified and not `data` request.POST is used as data.
          `request` is also saved to be access by renderers (as
          `fs.FIELD.renderer.request`).
        * if `with_prefix` is False then a prefix ``{Model}-{pk}`` is added to each data keys
        """
        if data is None and request is not None:
            if hasattr(request, 'environ') and hasattr(request, 'POST'):
                if request.environ.get('REQUEST_METHOD', '').upper() == 'POST':
                    data = request.POST or None

        original_model = model
        if model:
            if isinstance(model, type):
                try:
                    model = model()
                except Exception as 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, UnmappedInstanceError):
                    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 and model is not self._original_cls:
                        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)

        if data is not None and not with_prefix:
            if isinstance(data, multidict.UnicodeMultiDict):
                encoding = data.encoding
            else:
                encoding = config.encoding
            pk = fields._pk(self.model) or ''
            prefix = '%s-%s' % (self._original_cls.__name__, pk)
            if self._prefix:
                prefix = '%s-%s' % (self._prefix, prefix)
            data = SimpleMultiDict([('%s-%s' % (prefix, k), v)
                                    for k, v in data.items()],
                                   encoding=encoding)

        if data is None:
            self.data = None
        elif isinstance(data, multidict.UnicodeMultiDict):
            self.data = data
        elif isinstance(data, multidict.MultiDict):
            self.data = multidict.UnicodeMultiDict(multi=data,
                                                   encoding=config.encoding)
        elif hasattr(data, 'getall') and hasattr(data, 'getone'):
            self.data = data
        elif isinstance(data, (dict, list)):
            self.data = SimpleMultiDict(data, encoding=config.encoding)
        else:
            raise Exception(
                'unsupported data object %s.  currently only dicts and Paste multidicts are supported'
                % self.data)

        if not self.__sa__:
            return

        if session:
            self.session = session
        elif model:
            if '_obj_session' in locals():
                # model may be a temporary object, expunged from its session -- grab the existing reference
                self.session = _obj_session
            else:
                try:
                    o_session = object_session(model)
                except (AttributeError, UnmappedInstanceError):
                    pass  # non-SA object
                else:
                    if o_session:
                        self.session = o_session
        # if we didn't just instantiate (in which case object_session will be None),
        # the session should be the same as the object_session
        if self.session and model == original_model:
            try:
                o_session = object_session(self.model)
            except (AttributeError, UnmappedInstanceError):
                pass  # non-SA object
            else:
                if o_session and self.session is not o_session:
                    raise Exception(
                        'You may not explicitly bind to a session when your model already belongs to a different one'
                    )