コード例 #1
0
ファイル: views.py プロジェクト: aodag/pyramid_formalchemy
class ModelView(object):
    """A RESTful view bound to a model"""

    engine = TemplateEngine()
    pager_args = dict(
        link_attr={'class': 'ui-pager-link ui-state-default ui-corner-all'},
        curpage_attr={
            'class': 'ui-pager-curpage ui-state-highlight ui-corner-all'
        })

    actions_categories = ('buttons', )
    defaults_actions = actions.defaults_actions

    def __init__(self, context, request):
        self.context = context
        self.request = request
        self.session = request.session_factory

        self.fieldset_class = request.forms.FieldSet
        self.grid_class = request.forms.Grid
        if '_LOCALE_' not in request.cookies:
            locale = get_locale_name(request)
            request.cookies['_LOCALE_'] = locale
        if '_LOCALE_' not in request.cookies:
            theme = request.registry.settings.get('default_theme_name',
                                                  'smoothness')
            request.cookies['_LOCALE_'] = theme

    def models(self, **kwargs):
        """Models index page"""
        request = self.request
        models = []
        if isinstance(request.models, list):
            for model in request.models:
                if has_permission('view', model,
                                  request) or not hasattr(model, '__acl__'):
                    key = model.__name__
                    models.append(model)
        else:
            for key, obj in request.models.__dict__.iteritems():
                if not key.startswith('_'):
                    if Document is not None:
                        try:
                            if issubclass(obj, Document):
                                if has_permission('view', obj,
                                                  request) or not hasattr(
                                                      model, '__acl__'):
                                    models.append(obj)
                                continue
                        except:
                            pass
                    try:
                        class_mapper(obj)
                    except:
                        continue
                    if not isinstance(obj, type):
                        continue
                    if has_permission('view', obj,
                                      request) or not hasattr(obj, '__acl__'):
                        models.append(obj)

        results = {}
        for m in models:
            if request.format == 'html':
                url = request.fa_url(m.__name__)
            else:
                url = request.fa_url(m.__name__, request.format)
            results[I18NModel(m, request).plural] = url

        if kwargs.get('json'):
            return results
        return self.render(models=results)

    def sync(self, fs, id=None):
        """sync a record. If ``id`` is None add a new record else save current one."""
        if id:
            self.session.merge(fs.model)
        else:
            self.session.add(fs.model)
        event = events.AfterSyncEvent(fs.model, fs, self.request)
        zope.component.event.objectEventNotify(event)

    def validate(self, fs):
        """validate fieldset"""
        event = events.BeforeValidateEvent(fs.model, fs, self.request)
        zope.component.event.objectEventNotify(event)
        return fs.validate()

    def breadcrumb(self, fs=None, **kwargs):
        """return items to build the breadcrumb"""
        items = []
        request = self.request
        model_name = request.model_name
        id = request.model_id
        items.append((request.fa_url(), 'root', 'root_url'))
        if request.model_name:
            items.append((request.fa_url(model_name), model_name, 'model_url'))
        if id and hasattr(fs.model, '__unicode__'):
            items.append((request.fa_url(model_name, id),
                          u'%s' % self.context.get_instance(), 'instance_url'))
        elif id:
            items.append((request.fa_url(model_name, id), id, 'instance_url'))
        return items

    def render(self, **kwargs):
        """render the form as html or json"""
        request = self.request
        if request.format != 'html':
            meth = getattr(self, 'render_%s_format' % request.format, None)
            if meth is not None:
                return meth(**kwargs)
            else:
                raise NotFound()

        if request.model_class:
            request.model_class = model_class = I18NModel(
                request.model_class, request)
            request.model_label = model_label = model_class.label
            request.model_plural = model_plural = model_class.plural
        else:
            model_class = request.model_class
            model_label = model_plural = ''
        self.update_resources()
        kwargs.update(main=get_renderer(
            'pyramid_formalchemy:templates/admin/master.pt').implementation(),
                      model_class=model_class,
                      model_name=request.model_name,
                      model_label=model_label,
                      model_plural=model_plural,
                      breadcrumb=self.breadcrumb(**kwargs),
                      actions=request.actions,
                      F_=get_translator()),
        return kwargs

    def render_grid(self, **kwargs):
        """render the grid as html or json"""
        return self.render(is_grid=True, **kwargs)

    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

    def render_xhr_format(self, fs=None, **kwargs):
        self.request.response_content_type = 'text/html'
        if fs is not None:
            if 'field' in self.request.GET:
                field_name = self.request.GET.get('field')
                fields = fs.render_fields
                if field_name in fields:
                    field = fields[field_name]
                    return Response(field.render())
                else:
                    raise NotFound()
            return Response(fs.render())
        return Response('')

    def get_page(self, **kwargs):
        """return a ``webhelpers.paginate.Page`` used to display ``Grid``.
        """
        request = self.request

        def get_page_url(page, partial=None):
            url = "%s?page=%s" % (self.request.path, page)
            if partial:
                url += "&partial=1"
            return url

        options = dict(page=int(request.GET.get('page', '1')),
                       url=get_page_url)
        options.update(kwargs)
        if 'collection' not in options:
            query = self.session.query(request.model_class)
            options['collection'] = request.query_factory(request, query)
        collection = options.pop('collection')
        return Page(collection, **options)

    def get_fieldset(self, suffix='', id=None):
        """return a ``FieldSet`` object bound to the correct record for ``id``.
        """
        request = self.request
        model = id and request.model_instance or request.model_class
        form_name = request.model_name + suffix
        fs = getattr(request.forms, form_name, None)
        if fs is None:
            fs = getattr(request.forms, request.model_name,
                         self.fieldset_class)
        if isinstance(fs, type) and issubclass(fs, self.fieldset_class):
            fs = fs(request.model_class)
            if not isinstance(request.forms, list):
                # add default fieldset to form module eg: caching
                setattr(request.forms, form_name, fs)
        fs.engine = fs.engine or self.engine
        fs = id and fs.bind(model) or fs.copy()
        fs._request = request
        return fs

    def get_grid(self):
        """return a Grid object"""
        request = self.request
        model_name = request.model_name
        form_name = '%sGrid' % model_name
        if hasattr(request.forms, form_name):
            g = getattr(request.forms, form_name)
            g.engine = g.engine or self.engine
            g.readonly = True
            g._request = self.request
            self.update_grid(g)
            return g
        model = self.context.get_model()
        grid = self.grid_class(model)
        grid.engine = self.engine
        if not isinstance(request.forms, list):
            # add default grid to form module eg: caching
            setattr(request.forms, form_name, grid)
        grid = grid.copy()
        grid._request = self.request
        self.update_grid(grid)
        return grid

    def update_grid(self, grid):
        """Add edit and delete buttons to ``Grid``"""
        try:
            grid.edit
        except AttributeError:

            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'))

            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'))

            grid.append(Field('edit', fatypes.String, edit_link()))
            grid.append(Field('delete', fatypes.String, delete_link()))
            grid.readonly = True

    def update_resources(self):
        """A hook to add some fanstatic resources"""
        pass

    @actions.action()
    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)

    @actions.action()
    def show(self):
        id = self.request.model_id
        fs = self.get_fieldset(suffix='View', id=id)
        fs.readonly = True

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

        return self.render(fs=fs, id=id)

    @actions.action()
    def new(self):
        fs = self.get_fieldset(suffix='Add')
        fs = fs.bind(session=self.session, request=self.request)

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

        return self.render(fs=fs, id=None)

    @actions.action('new')
    def create(self):
        request = self.request
        fs = self.get_fieldset(suffix='Add')

        event = events.BeforeRenderEvent(fs.model, 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(data=data,
                     session=self.session,
                     request=request,
                     with_prefix=with_prefix)
        #try:
        #    fs = fs.bind(data=data, session=self.session, request=request, with_prefix=with_prefix)
        #except Exception:
        #    # non SA forms
        #    fs = fs.bind(self.context.get_model(), data=data, session=self.session,
        #                 request=request, with_prefix=with_prefix)

        if self.validate(fs):
            fs.sync()
            self.sync(fs)
            self.session.flush()
            if request.format in ('html', 'xhr'):
                if request.is_xhr or request.format == 'xhr':
                    return Response(content_type='text/plain')
                next = request.POST.get('next') or request.fa_url(
                    request.model_name)
                return exc.HTTPFound(location=next)
            else:
                fs.rebind(fs.model, data=None)
                return self.render(fs=fs)
        return self.render(fs=fs, id=None)

    @actions.action()
    def edit(self):
        id = self.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)

        return self.render(fs=fs, id=id)

    @actions.action('edit')
    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)

    def delete(self):
        request = self.request
        record = request.model_instance

        event = events.BeforeDeleteEvent(record, self.request)
        zope.component.event.objectEventNotify(event)

        if record:
            self.session.delete(record)
        else:
            raise NotFound()

        if request.format == 'html':
            if request.is_xhr or request.format == 'xhr':
                return Response(content_type='text/plain')
            return exc.HTTPFound(location=request.fa_url(request.model_name))
        return self.render(id=request.model_id)

    def autocomplete(self, *args, **kwargs):
        filter_term = "%s%%" % self.request.params.get('term')
        filter_attr = getattr(self.request.model_class,
                              self.request.params.get('filter_by'))
        query = self.session.query(self.request.model_class.id,
                                   filter_attr).filter(
                                       filter_attr.ilike(filter_term))
        items = self.request.query_factory(self.request, query)
        return Response(json.dumps([{
            'label': x[1],
            'value': x[0]
        } for x in items]),
                        content_type='text/plain')
コード例 #2
0
class ModelView(Base):

    engine = TemplateEngine()

    def breadcrumb(self, **kwargs):
        """return items to build the breadcrumb"""
        request = self.request
        if request.model_name is None:
            return actions.Actions()

        models = self.models(i18n=True, json=True)

        if len(models) == 1:
            return actions.Actions()

        items = actions.Actions(
            actions.Option('jump_to', content=_('Jump to ...')),
            actions.Option('model_index',
                           content=_('Models index'),
                           value='request.fa_url()'),
        )

        models = sorted([v for v in models.items()])
        for name, url in models:
            items.append(
                actions.Option('%s_listing' % name.lower(),
                               content=name,
                               value='string:%s' % url))
        return items

    def index(self, *args, **kwargs):
        kwargs['pager'] = ''
        return Base.index(self, *args, **kwargs)

    def get_page(self, **kwargs):
        if 'collection' not in kwargs:
            request = self.request
            params = request.params
            query = request.session_factory.query(request.model_class)
            collection = request.query_factory(request, query, id=None)
            fields = request.model_class._sa_class_manager
            # FIXME: use id by default but should use pk field
            sidx = params.get('sidx', 'id').decode()
            if sidx and fields.has_key(sidx):
                sidx = fields[sidx]
                sord = params.get('sord', 'asc').decode().lower()
                if sord in ['asc', 'desc']:
                    collection = collection.order_by(getattr(sidx, sord)())
            if 'searchField' in params:
                field = fields.get(params['searchField'], None)
                if field:
                    op = params['searchOper']
                    value = params['searchString']
                    if op == 'cn':
                        value = '%%%s%%' % value
                        filter = field.ilike(value)
                    else:
                        filter = field == value
                    collection = collection.filter(filter)
            kwargs.update(collection=collection)
        if 'items_per_page' not in kwargs:
            kwargs.update(items_per_page=int(self.request.GET.get('rows', 20)))
        return Base.get_page(self, **kwargs)

    def render_xhr_format(self, fs=None, **kwargs):
        resp = Base.render_xhr_format(self, fs=fs, **kwargs)
        if fs and self.request.POST and 'field' not in self.request.GET:
            flash = utils.Flash()
            if fs.errors:
                errors = [
                    f.label_text or fs.prettify(f.key)
                    for f in fs.render_fields.values() if f.errors
                ]
                flash.error('Field(s) %s have errors' % ','.join(errors))
            else:
                flash.info('Record saved')
            resp.unicode_body += flash.render()
        return resp

    def update_resources(self):
        """A hook to add some fanstatic resources"""
        theme = getattr(self.request, 'cookies',
                        {}).get('_THEME_', 'smoothness')
        getattr(jqueryui, theme).need()
        fa_admin.need()
        lang = getattr(self.request, 'cookies', {}).get('_LOCALE_', 'en')
        needed_resource = getattr(jqgrid, 'jqgrid_i18n_%s' % lang,
                                  jqgrid.jqgrid_i18n_en)
        needed_resource.need()
        fa_jqgrid.need()

    def update_grid(self, grid, *args, **kwargs):
        metadatas = ('width', 'align', 'fixed', 'search', 'stype',
                     'searchoptions')
        for field in grid.render_fields.values():
            metadata = dict(search=0, sortable=1, id=field.key, name=field.key)
            searchoptions = dict(sopt=['eq', 'cn'])
            if field.is_relation:
                metadata.update(width=100, sortable=0)
            elif isinstance(field.type, (utils.Color, utils.Slider)):
                metadata.update(width=50, align='center')
            elif isinstance(field.type, fatypes.Text):
                field.set(renderer=ellipsys(field.renderer))
                metadata.update(search=1)
            elif isinstance(field.type, (fatypes.String, fatypes.Unicode)):
                metadata.update(search=1)
            elif isinstance(field.type, (fatypes.Date, fatypes.Integer)):
                metadata.update(width=70, align='center')
            elif isinstance(field.type, fatypes.DateTime):
                metadata.update(width=120, align='center')
            elif isinstance(field.type, fatypes.Boolean):
                metadata.update(width=30, align='center')
            if metadata['search']:
                metadata['searchoptions'] = searchoptions
            metadata = dict(json=dumps(metadata))
            metadata['label'] = dumps(field.label())
            field.set(metadata=metadata)
コード例 #3
0
from c2cgeoportal import (
    formalchemy_default_zoom,
    formalchemy_default_x, formalchemy_default_y,
    formalchemy_available_functionalities)

__all__ = [
    'Functionality', 'User', 'Role', 'LayerGroup', 'Theme', 'Layer',
    'RestrictionArea', 'LayerGrid', 'LayerGroupGrid', 'ThemeGrid',
    'FunctionalityGrid', 'RestrictionAreaGrid', 'RoleGrid', 'UserGrid']


log = logging.getLogger(__name__)
_ = TranslationStringFactory('c2cgeoportal')

fa_config.encoding = 'utf-8'
fa_config.engine = TemplateEngine()

fanstatic_lib = Library('admin', 'static')
admin_js = Resource(
    fanstatic_lib,
    'build/admin/admin.js',
    depends=[fanstatic_resources.jqueryui])
admin_css = Resource(
    fanstatic_lib,
    'build/admin/admin.css',
    depends=[fanstatic_resources.fa_uiadmin_css])

# HACK to invoke fanstatic to inject a script which content is dynamic:
# the content of the script sets OpenLayers.ImgPath to an url that is
# dynamically generated using request.static_url
olimgpath_js = None
コード例 #4
0
ファイル: pyramid.py プロジェクト: pgiraud/fa.jquery
class ModelView(Base):

    engine = TemplateEngine()

    def breadcrumb(self, fs=None, **kwargs):
        """return items to build the breadcrumb"""
        request = self.request
        model_name = request.model_name
        models = self.models(json=True)

        if len(models) == 1:
            return []

        items = [
            ('', 'Jump to ...', ''),
            (request.fa_url(), 'Models index', ''),
        ]

        models = sorted([v for v in models.items()])
        for name, url in models:
            items.append((request.fa_url(name), name, 'model_url'))
        return items

    def index(self, *args, **kwargs):
        kwargs['pager'] = ''
        return Base.index(self, *args, **kwargs)

    def get_page(self, **kwargs):
        if 'collection' not in kwargs:
            request = self.request
            params = request.params
            query = request.session_factory.query(request.model_class)
            collection = request.query_factory(request, query, id=None)
            fields = request.model_class._sa_class_manager
            # FIXME: use id by default but should use pk field
            sidx = params.get('sidx', 'id').decode()
            if sidx and fields.has_key(sidx):
                sidx = fields[sidx]
                sord = params.get('sord', 'asc').decode().lower()
                if sord in ['asc', 'desc']:
                    collection = collection.order_by(getattr(sidx, sord)())
            if 'searchField' in params:
                field = fields.get(params['searchField'], None)
                if field:
                    op = params['searchOper']
                    value = params['searchString']
                    if op == 'cn':
                        value = '%%%s%%' % value
                        filter = field.ilike(value)
                    else:
                        filter = field == value
                    collection = collection.filter(filter)
            kwargs.update(collection=collection)
        if 'items_per_page' not in kwargs:
            kwargs.update(items_per_page=int(self.request.GET.get('rows', 20)))
        return Base.get_page(self, **kwargs)

    def render_xhr_format(self, fs=None, **kwargs):
        resp = Base.render_xhr_format(self, fs=fs, **kwargs)
        if fs and self.request.POST and 'field' not in self.request.GET:
            flash = utils.Flash()
            if fs.errors:
                errors = [
                    f.label_text or fs.prettify(f.key)
                    for f in fs.render_fields.values() if f.errors
                ]
                flash.error('Field(s) %s have errors' % ','.join(errors))
            else:
                flash.info('Record saved')
            resp.unicode_body += flash.render()
        return resp

    def update_grid(self, grid, *args, **kwargs):
        metadatas = ('width', 'align', 'fixed', 'search', 'stype',
                     'searchoptions')
        for field in grid.render_fields.values():
            metadata = dict(search=0, sortable=1, id=field.key, name=field.key)
            searchoptions = dict(sopt=['eq', 'cn'])
            if field.is_relation:
                metadata.update(width=100, sortable=0)
            elif isinstance(field.type, (utils.Color, utils.Slider)):
                metadata.update(width=50, align='center')
            elif isinstance(field.type, fatypes.Text):
                field.set(renderer=renderers.ellipsys(field.renderer))
                metadata.update(search=1)
            elif isinstance(field.type, (fatypes.String, fatypes.Unicode)):
                metadata.update(search=1)
            elif isinstance(field.type, (fatypes.Date, fatypes.Integer)):
                metadata.update(width=70, align='center')
            elif isinstance(field.type, fatypes.DateTime):
                metadata.update(width=120, align='center')
            elif isinstance(field.type, fatypes.Boolean):
                metadata.update(width=30, align='center')
            if metadata['search']:
                metadata['searchoptions'] = searchoptions
            metadata = dict(json=dumps(metadata))
            field.set(metadata=metadata)