Ejemplo n.º 1
0
    def new(self,
            model,
            source=None,
            kind=0,
            text=None,
            domain=None,
            context=None,
            **kw):
        """Create new search view...

        @param model: the model
        @param source: the source, in case of m2m, m2o search
        @param kind: 0=normal, 1=m2o, 2=m2m
        @param text: do `name_search` if text is provided
        @param domain: the domain
        @param context: the context
        """

        params = TinyDict()

        params.model = model
        params.domain = domain or []
        params.context = context or {}

        params.source = source
        params.selectable = kind
        params.limit = params.limit or 50

        ctx = dict(rpc.session.context, **(params.context or {}))
        params.ids = []
        proxy = rpc.RPCProxy(model)
        params.search_text = False

        # parent's search_view has no business being in m2o or m2m
        if '_terp_context' in params and 'search_view' in params[
                '_terp_context']:
            params.get('_terp_context').pop('search_view', None)
        if text:
            params.search_text = True
            ids = proxy.name_search(text, params.domain or [], 'ilike', ctx,
                                    False)

            if ids:
                params.ids = [id[0] for id in ids]

                # For m2o, when name_search is called, then its result will be added to existing domain
                params.domain.append(('id', 'in', params.ids))

                params.count = len(ids)
            else:
                params.context['default_name'] = ustr(text)
        elif 'default_name' in params.context:
            del params.context['default_name']

        if kw.get('return_to'):
            params['return_to'] = ast.literal_eval(kw['return_to'])

        return self.create(params)
Ejemplo n.º 2
0
    def new(self, model, source=None, kind=0, text=None, domain=None, context=None, **kw):
        """Create new search view...

        @param model: the model
        @param source: the source, in case of m2m, m2o search
        @param kind: 0=normal, 1=m2o, 2=m2m
        @param text: do `name_search` if text is provided
        @param domain: the domain
        @param context: the context
        """

        params = TinyDict()

        params.model = model
        params.domain = domain or []
        params.context = context or {}

        params.source = source
        params.selectable = kind
        params.limit = params.limit or 50

        ctx = dict(rpc.session.context,
                   **(params.context or {}))
        params.ids = []
        proxy = rpc.RPCProxy(model)
        params.search_text = False

        # parent's search_view has no business being in m2o or m2m
        if '_terp_context' in params and 'search_view' in params['_terp_context']:
            params.get('_terp_context').pop('search_view', None)

        if text:
            params.search_text = True
            ids = proxy.name_search(text, params.domain or [], 'ilike', ctx, False)

            if ids:
                params.ids = [id[0] for id in ids]

                # For m2o, when name_search is called, then its result will be added to existing domain
                params.domain.append(('id','in', params.ids))

                params.count = len(ids)
            else:
                params.context['default_name'] = ustr(text)
        elif 'default_name'in params.context:
            del params.context['default_name']

        if kw.get('return_to'):
            params['return_to'] = ast.literal_eval(kw['return_to'])
            
        return self.create(params)
Ejemplo n.º 3
0
    def new(self, model, source=None, kind=0, text=None, domain=[], context={}):
        """Create new search view...

        @param model: the model
        @param source: the source, in case of m2m, m2o search
        @param kind: 0=normal, 1=m2o, 2=m2m
        @param text: do `name_search` if text is provided
        @param domain: the domain
        @param context: the context
        """

        params = TinyDict()

        params.model = model
        params.domain = domain
        params.context = context
        params.limit = params.limit or 20

        params.source = source
        params.selectable = kind
        ctx = rpc.session.context.copy()
        ctx.update(params.context or {})

        
        if text: #Original
            if 'search_field' in ctx: #KDVN Team Added       
                params.search_domain = [(ctx['search_field'],ctx['operator'], text)] #KDVN Team Added
            else:#KDVN Team Added
                params.search_domain = [('name', 'ilike', text)] #Original
    
        params.ids = []
        proxy = rpc.RPCProxy(model)
        ids = proxy.name_search(text or '', params.domain or [], 'ilike', ctx)
        if ids:
            params.ids = [id[0] for id in ids]
            if len(ids) < params.limit:
                count = len(ids)
            else:
                if text and 'search_field' in ctx:
                    count = proxy.search_count(params.domain+params.search_domain, ctx)
                else:
                    count = proxy.search_count(params.domain, ctx)
            params.count = count
        return self.create(params)
Ejemplo n.º 4
0
    def __init__(self, **attrs):
        super(M2M, self).__init__(**attrs)

        ids = None
        params = getattr(cherrypy.request, 'terp_params', None)
        if not params:
            params = TinyDict()
            params.model = attrs.get('relation', 'model')
            params.ids = attrs.get('value', [])
            params.name = attrs.get('name', '')

        current = params.chain_get(self.name)
        if current and params.source == self.name:
            ids = current.ids

        self.model = attrs.get('relation', 'model')
        self.link = attrs.get('link', 1)
        self.onchange = None # override onchange in js code

        self.relation = attrs.get('relation', '')
        self.domain = attrs.get('domain', [])
        self.context = attrs.get('context', {}) or {}        

        view = attrs.get('views', {})
        mode = str(attrs.get('mode', 'tree,form')).split(',')

        self.view = view

        view_mode = mode
        view_type = mode[0]

        self.switch_to = view_mode[-1]
        if view_type == view_mode[-1]: self.switch_to = view_mode[0]
        
        if ids is None:
            ids = attrs.get('value', [])

        id = (ids or None) and ids[0]

        pprefix = ''
        if '/' in self.name:
            pprefix = self.name[:self.name.rindex('/')]

        current = params.chain_get(self.name)

        if not current:
            current = TinyDict()

        current.offset = current.offset or 0
        current.limit = current.limit or 0
        current.count = len(ids or [])

        if current.view_mode: view_mode = current.view_mode
        if current.view_type: view_type = current.view_type

        if current and params.source == self.name:
            id = current.id

        id = id or None

        current.model = self.model
        current.id = id

        if isinstance(ids, tuple):
            ids = list(ids)

        current.ids = ids or []
        current.view_mode = view_mode
        current.view_type = view_type
        current.domain = current.domain or []
        current.context = current.context or {}
        
        if isinstance(self.context, basestring):
            ctx = cherrypy.request.terp_record
            ctx['current_date'] = time.strftime('%Y-%m-%d')
            ctx['time'] = time
            ctx['context'] = current.context
            ctx['active_id'] = current.id or False

            # XXX: parent record for O2M
            #if self.parent:
            #    ctx['parent'] = EvalEnvironment(self.parent)

            try:
                ctx = tools.expr_eval(self.context, ctx)
                current.context.update(ctx)
            except:
                pass

        if current.view_type == 'tree' and self.readonly:
            self.editable = False

        if self.editable is False:
            selectable = 0
        else:
            selectable = 2

        # try to get original input values if creating validation form
        if not params.filter_action:
            try:
                current.ids = eval(cherrypy.request.terp_data.get(self.name))
            except:
                pass

        self.screen = Screen(current, prefix=self.name, views_preloaded=view,
                             editable=False, readonly=self.editable,
                             selectable=selectable, nolinks=self.link)
        
        if view_type == 'tree':
            limit = 20
            if self.screen.widget.attr_limit:
                limit = self.screen.widget.attr_limit
            if current.limit == 0:
                current.limit = limit
                
            self.screen.widget.pageable = Pager(ids=current.ids, offset=current.offset, limit=current.limit,
                                                count=current.count, def_limit=limit)

        self.screen.widget.checkbox_name = False
        self.screen.widget.m2m = True

        self.validator = validators.many2many()
Ejemplo n.º 5
0
    def __init__(self, **attrs):
        #FIXME: validation error in `Pricelist Version`
        attrs['required'] = False

        super(O2M, self).__init__(**attrs)

        self.new_attrs = { 'text': _("New"), 'help': _('Create new record.')}
        self.default_get_ctx = attrs.get('default_get', {}) or attrs.get('context', {})

#        self.colspan = 4
#        self.nolabel = True

        # get top params dictionary
        params = cherrypy.request.terp_params

        pprefix = ''
        if '/' in self.name:
            pprefix = self.name[:self.name.rindex('/')]

        pparams = params.chain_get(pprefix)
        if (pparams and not pparams.id) or (not pparams and not params.id):
            self.new_attrs = { 'text': _("Save/New"), 'help': _('Save parent record.')}

        self.parent_id = params.id
        if pparams:
            self.parent_id = pparams.id

        # get params for this field
        current = params.chain_get(self.name)

        self.model = attrs['relation']
        self.link = attrs.get('link', 1)
        self.onchange = None # override onchange in js code

        view = attrs.get('views', {})
        mode = str(attrs.get('mode', 'tree,form')).split(',')

        self.view = view
        
        view_mode = mode
        view_type = mode[0]
        if not current:
            current = TinyDict()

        if current.view_mode: view_mode = current.view_mode
        if current.view_type: view_type = current.view_type

        self.switch_to = view_mode[-1]
        if view_type == view_mode[-1]: self.switch_to = view_mode[0]
        
        ids = attrs.get('value') or []
        if not isinstance(ids, list):
            ids = [ids]
        
        if ids and isinstance(ids[0], dict):
            ids = []
            
        if ids and isinstance(ids[0], tuple):
            ids = [i[1] for i in ids]
            
        id = (ids or None) and ids[0]
        
        if current and params.source and self.name in params.source.split('/'):
            id = current.id

        id = id or None    
        current.model = self.model
        current.id = id
        current.ids = ids
        current.view_mode = view_mode
        current.view_type = view_type
        current.domain = current.domain or []
        current.context = current.context or {}

        if self.default_get_ctx:
            ctx = cherrypy.request.terp_record
            ctx['current_date'] = time.strftime('%Y-%m-%d')
            ctx['time'] = time
            ctx['context'] = current.context
            ctx['active_id'] = self.parent_id or False

            # XXX: parent record for O2M
            #if self.parent:
            #    ctx['parent'] = EvalEnvironment(self.parent)

            try:
                ctx = tools.expr_eval("dict(%s)" % self.default_get_ctx, ctx)
                current.context.update(ctx)
            except:
                pass

        current.offset = current.offset or 0
        current.limit = current.limit or 0 
        current.count = len(ids or [])

        if current.view_type == 'tree' and self.readonly:
            self.editable = False

        self.screen = Screen(current, prefix=self.name, views_preloaded=view,
                             editable=self.editable, readonly=self.readonly,
                             selectable=0, nolinks=self.link)
        self.id = id
        self.ids = ids

        if view_type == 'tree':
            limit = 20
            #self.screen.widget.pageable=False
            if self.screen.widget.attr_limit:
                limit = self.screen.widget.attr_limit
            if current.limit == 0:
                current.limit = limit
                
            self.screen.widget.pageable = Pager(ids=current.ids, offset=current.offset, limit=current.limit,
                                                count=current.count, def_limit=limit)

            self.id = None

        pager_info = None
        if view_type == 'form':
            c = (self.screen.ids or 0) and len(self.screen.ids)
            i = 0

            if c and self.screen.id in self.screen.ids:
                i = self.screen.ids.index(self.screen.id) + 1

            self.pager_info = '[%s/%s]' % (i, c)
Ejemplo n.º 6
0
    def __init__(self, **attrs):
        super(M2M, self).__init__(**attrs)

        ids = None
        params = getattr(cherrypy.request, 'terp_params', None)
        if not params:
            params = TinyDict()
            params.model = attrs.get('relation', 'model')
            params.ids = attrs.get('value', [])
            params.name = attrs.get('name', '')

        current = params.chain_get(self.name)
        if current and params.source == self.name:
            ids = current.ids

        self.model = attrs.get('relation', 'model')
        self.link = attrs.get('link', None)
        self.onchange = None # override onchange in js code

        self.relation = attrs.get('relation', '')
        self.domain = attrs.get('domain', [])
        self.context = attrs.get('context', {}) or {}        

        view = attrs.get('views', {})
        mode = str(attrs.get('mode', 'tree,form')).split(',')

        self.view = view

        view_mode = mode
        view_type = mode[0]

        self.switch_to = view_mode[-1]
        if view_type == view_mode[-1]: self.switch_to = view_mode[0]

        if ids is None:
            ids = attrs.get('value', [])

        id = (ids or None) and ids[0]
        
        pprefix = ''
        if '/' in self.name:
            pprefix = self.name[:self.name.rindex('/')]
        
        if self.name == params.source and params.sort_key and ids:
            self.domain.append(('id', 'in', ids))
            ids = rpc.RPCProxy(self.model).search(self.domain, 0, 0, params.sort_key+ ' '+params.sort_order, self.context)
            id = ids[0]
        current = params.chain_get(self.name)

        if not current:
            current = TinyDict()

        current.offset = current.offset or 0
        current.limit = current.limit or 50
        current.count = len(ids or [])

        if current.view_mode: view_mode = current.view_mode
        if current.view_type: view_type = current.view_type

        if current and params.source == self.name:
            id = current.id

        id = id or None

        current.model = self.model
        current.id = id

        if isinstance(ids, tuple):
            ids = list(ids)

        current.ids = ids or []
        current.view_mode = view_mode
        current.view_type = view_type
        current.domain = current.domain or []
        current.context = current.context or {}

        if isinstance(self.context, basestring):
            # XXX: parent record for O2M
            #if self.parent:
            #    ctx['parent'] = EvalEnvironment(self.parent)

            try:
                ctx = expr_eval(
                        self.context,
                        dict(cherrypy.request.terp_record,
                             context=current.context,
                             active_id=current.id or False))
                current.context.update(ctx)
            except:
                pass

        if current.view_type == 'tree' and self.readonly:
            self.editable = False

        if self.editable is False:
            selectable = 0
        else:
            selectable = 2

        # try to get original input values if creating validation form
        if not params.filter_action:
            try:
                current.ids = eval(cherrypy.request.terp_data.get(self.name))
            except:
                pass

        self.screen = Screen(current, prefix=self.name, views_preloaded=view,
                             editable=self.editable, readonly=self.editable,
                             selectable=selectable, nolinks=self.link, **{'_m2m': 1})

        self.screen.widget.checkbox_name = False
        self.screen.widget.m2m = True

        self.validator = validators.many2many()
Ejemplo n.º 7
0
    def __init__(self, **attrs):
        super(M2M, self).__init__(**attrs)

        ids = None
        params = getattr(cherrypy.request, "terp_params", None)
        if not params:
            params = TinyDict()
            params.model = attrs.get("relation", "model")
            params.ids = attrs.get("value", [])
            params.name = attrs.get("name", "")

        current = params.chain_get(self.name)
        if current and params.source == self.name:
            ids = current.ids

        self.model = attrs.get("relation", "model")
        self.link = attrs.get("link", None)
        self.onchange = None  # override onchange in js code

        self.relation = attrs.get("relation", "")
        self.domain = attrs.get("domain", [])
        self.context = attrs.get("context", {}) or {}

        view = attrs.get("views", {})
        mode = str(attrs.get("mode", "tree,form")).split(",")

        self.view = view

        view_mode = mode
        view_type = mode[0]

        self.switch_to = view_mode[-1]
        if view_type == view_mode[-1]:
            self.switch_to = view_mode[0]

        if ids is None:
            ids = attrs.get("value") or []

        id = (ids or None) and ids[0]

        pprefix = ""
        if "/" in self.name:
            pprefix = self.name[: self.name.rindex("/")]

        current = params.chain_get(self.name)

        if not current:
            current = TinyDict()

        current.offset = current.offset or 0
        current.limit = current.limit or 50
        current.count = len(ids or [])

        if isinstance(ids, tuple):
            ids = list(ids)

        if self.name == params.source and params.sort_key and ids:
            # reorder ids based on supplier criteria (sort_key, sort_order)
            domain = current.domain or []
            domain.append(("id", "in", ids))
            ids = rpc.RPCProxy(self.model).search(
                domain, 0, 0, params.sort_key + " " + params.sort_order, current.context
            )
            id = ids[0]

        if current.view_mode:
            view_mode = current.view_mode
        if current.view_type:
            view_type = current.view_type

        if current and params.source == self.name:
            id = current.id

        id = id or None

        current.model = self.model
        current.id = id

        current.ids = ids or []
        current.view_mode = view_mode
        current.view_type = view_type
        current.domain = current.domain or []
        current.context = current.context or {}

        if isinstance(self.context, basestring):
            # XXX: parent record for O2M
            # if self.parent:
            #    ctx['parent'] = EvalEnvironment(self.parent)

            try:
                ctx = expr_eval(
                    self.context,
                    dict(cherrypy.request.terp_record, context=current.context, active_id=current.id or False),
                )
                current.context.update(ctx)
            except:
                pass

        if current.view_type == "tree" and self.readonly:
            self.editable = False

        if self.editable is False:
            selectable = 0
        else:
            selectable = 2

        # try to get original input values if creating validation form
        if not params.filter_action:
            try:
                current.ids = eval(cherrypy.request.terp_data.get(self.name))
            except:
                pass

        self.screen = Screen(
            current,
            prefix=self.name,
            views_preloaded=view,
            editable=self.editable,
            readonly=self.editable,
            selectable=selectable,
            nolinks=self.link,
            **{"_m2m": 1}
        )

        self.screen.widget.checkbox_name = False
        self.screen.widget.m2m = True

        self.validator = validators.many2many()
Ejemplo n.º 8
0
    def __init__(self, **attrs):
        super(M2M, self).__init__(**attrs)

        ids = None
        params = getattr(cherrypy.request, 'terp_params', None)
        if not params:
            params = TinyDict()
            params.model = attrs.get('relation', 'model')
            params.ids = attrs.get('value', [])
            params.name = attrs.get('name', '')

        current = params.chain_get(self.name)
        if current and params.source == self.name:
            ids = current.ids

        self.model = attrs.get('relation', 'model')
        self.link = attrs.get('link', None)
        self.onchange = None  # override onchange in js code

        self.relation = attrs.get('relation', '')
        self.domain = attrs.get('domain', [])
        self.context = attrs.get('context', {}) or {}

        view = attrs.get('views', {})
        mode = str(attrs.get('mode', 'tree,form')).split(',')

        self.view = view

        view_mode = mode
        view_type = mode[0]

        self.switch_to = view_mode[-1]
        if view_type == view_mode[-1]: self.switch_to = view_mode[0]

        if ids is None:
            ids = attrs.get('value', [])

        id = (ids or None) and ids[0]

        pprefix = ''
        if '/' in self.name:
            pprefix = self.name[:self.name.rindex('/')]

        if self.name == params.source and params.sort_key and ids:
            self.domain.append(('id', 'in', ids))
            ids = rpc.RPCProxy(self.model).search(
                self.domain, 0, 0, params.sort_key + ' ' + params.sort_order,
                self.context)
            id = ids[0]
        current = params.chain_get(self.name)

        if not current:
            current = TinyDict()

        current.offset = current.offset or 0
        current.limit = current.limit or 50
        current.count = len(ids or [])

        if current.view_mode: view_mode = current.view_mode
        if current.view_type: view_type = current.view_type

        if current and params.source == self.name:
            id = current.id

        id = id or None

        current.model = self.model
        current.id = id

        if isinstance(ids, tuple):
            ids = list(ids)

        current.ids = ids or []
        current.view_mode = view_mode
        current.view_type = view_type
        current.domain = current.domain or []
        current.context = current.context or {}

        if isinstance(self.context, basestring):
            # XXX: parent record for O2M
            #if self.parent:
            #    ctx['parent'] = EvalEnvironment(self.parent)

            try:
                ctx = expr_eval(
                    self.context,
                    dict(cherrypy.request.terp_record,
                         context=current.context,
                         active_id=current.id or False))
                current.context.update(ctx)
            except:
                pass

        if current.view_type == 'tree' and self.readonly:
            self.editable = False

        if self.editable is False:
            selectable = 0
        else:
            selectable = 2

        # try to get original input values if creating validation form
        if not params.filter_action:
            try:
                current.ids = eval(cherrypy.request.terp_data.get(self.name))
            except:
                pass

        self.screen = Screen(current,
                             prefix=self.name,
                             views_preloaded=view,
                             editable=self.editable,
                             readonly=self.editable,
                             selectable=selectable,
                             nolinks=self.link,
                             **{'_m2m': 1})

        self.screen.widget.checkbox_name = False
        self.screen.widget.m2m = True

        self.validator = validators.many2many()
Ejemplo n.º 9
0
    def __init__(self, **attrs):
        #FIXME: validation error in `Pricelist Version`
        attrs['required'] = False

        super(O2M, self).__init__(**attrs)

        self.new_attrs = {'text': _("New"), 'help': _('Create new record.')}
        self.default_get_ctx = attrs.get('default_get', {}) or attrs.get(
            'context', {})

        # get top params dictionary
        params = cherrypy.request.terp_params
        self.source = params.source
        self.edition = params.o2m_edit
        pprefix = ''
        if '/' in self.name:
            pprefix = self.name[:self.name.rindex('/')]

        pparams = params.chain_get(pprefix)
        if (pparams and not pparams.id) or (not pparams and not params.id):
            self.new_attrs = {
                'text': _("Save/New"),
                'help': _('Save parent record.')
            }

        self.parent_id = params.id
        if pparams:
            self.parent_id = pparams.id

        # get params for this field
        current = params.chain_get(self.name)

        self.model = attrs['relation']
        self.link = attrs.get('link', '')
        self.onchange = None  # override onchange in js code

        view = attrs.get('views', {})
        mode = str(attrs.get('mode', 'tree,form')).split(',')

        self.view = view

        view_mode = mode
        view_type = mode[0]
        self.view_type = view_type

        if not current:
            current = TinyDict()

        if current.view_mode: view_mode = current.view_mode
        if current.view_type: view_type = current.view_type

        self.switch_to = view_mode[-1]
        if view_type == view_mode[-1]: self.switch_to = view_mode[0]

        ids = attrs.get('value') or []
        if not isinstance(ids, list):
            ids = [ids]

        current.offset = current.offset or 0
        current.limit = current.limit or 50
        current.count = len(ids or [])

        if current.limit != -1 and not params.sort_key:
            ids = ids[current.offset:current.offset + current.limit]

        if ids:
            if isinstance(ids[0], dict):
                current.default_data = ids
                for item in current.default_data:
                    self.default_value.append(OneToMany.create(item))
                    item['id'] = 0
                ids = []
            elif isinstance(ids[0], tuple):
                [current_id[1] for current_id in ids]

        id = (ids or None) and ids[0]

        if self.name == self.source or self.name == params.source:
            if params.sort_key and ids:
                domain = current.domain or []
                domain.append(('id', 'in', ids))
                limit = current.limit
                if current.limit == -1:
                    limit = 0
                ids = rpc.RPCProxy(self.model).search(
                    domain, current.offset, limit,
                    params.sort_key + ' ' + params.sort_order, current.context)
                id = ids[0]
        if current and params.source and isinstance(
                params.source,
                basestring) and self.name in params.source.split('/'):
            id = current.id

        id = id or None

        current.model = self.model
        current.id = id
        current.ids = ids
        current.view_mode = view_mode
        current.view_type = view_type
        current.domain = current.domain or []
        current.context = current.context or {}

        group_by_ctx = ''
        if self.default_get_ctx:
            ctx = dict(cherrypy.request.terp_record,
                       context=current.context,
                       active_id=self.parent_id or False)
            ctx[attrs['name']] = ids
            # XXX: parent record for O2M
            #if self.parent:
            #    ctx['parent'] = EvalEnvironment(self.parent)

            try:
                context = ctx.copy()
                ctx = expr_eval("dict(%s)" % self.default_get_ctx, context)
                ctx.update(
                    expr_eval("dict(%s)" % attrs.get('context', '{}'),
                              context))
                current.context.update(ctx)
            except:
                pass

            if ctx and ctx.get('group_by'):
                group_by_ctx = ctx.get('group_by')

        # Group By for one2many list.
        if group_by_ctx:
            current.group_by_ctx = group_by_ctx
            current.domain = [('id', 'in', ids)]

        if current.view_type == 'tree' and self.readonly:
            self.editable = False

        if 'default_name' in current.context:
            del current.context['default_name']

        self.screen = Screen(current,
                             prefix=self.name,
                             views_preloaded=view,
                             editable=self.editable,
                             readonly=self.readonly,
                             selectable=0,
                             nolinks=self.link,
                             _o2m=1)

        self.id = id
        self.ids = ids

        if view_type == 'tree':
            self.id = None

        elif view_type == 'form':
            records_count = len(self.screen.ids or [])

            current_record = 0
            if records_count and self.screen.id in self.screen.ids:
                current_record = self.screen.ids.index(self.screen.id) + 1
                self.pager_info = _('%d of %d') % (current_record,
                                                   records_count)
            else:
                self.pager_info = _('- of %d') % (records_count)
Ejemplo n.º 10
0
    def __init__(self, **attrs):
        #FIXME: validation error in `Pricelist Version`
        attrs['required'] = False

        super(O2M, self).__init__(**attrs)

        self.new_attrs = { 'text': _("New"), 'help': _('Create new record.')}
        self.default_get_ctx = attrs.get('default_get', {}) or attrs.get('context', {})

        # get top params dictionary
        params = cherrypy.request.terp_params
        self.source = params.source
        self.edition = params.o2m_edit
        pprefix = ''
        if '/' in self.name:
            pprefix = self.name[:self.name.rindex('/')]

        pparams = params.chain_get(pprefix)
        if (pparams and not pparams.id) or (not pparams and not params.id):
            self.new_attrs = { 'text': _("Save/New"), 'help': _('Save parent record.')}

        self.parent_id = params.id
        if pparams:
            self.parent_id = pparams.id

        # get params for this field
        current = params.chain_get(self.name)

        self.model = attrs['relation']
        self.link = attrs.get('link', '')
        self.onchange = None # override onchange in js code

        view = attrs.get('views', {})
        mode = str(attrs.get('mode', 'tree,form')).split(',')

        self.view = view

        view_mode = mode
        view_type = mode[0]
        self.view_type = view_type
        
        if not current:
            current = TinyDict()

        if current.view_mode: view_mode = current.view_mode
        if current.view_type: view_type = current.view_type

        self.switch_to = view_mode[-1]
        if view_type == view_mode[-1]: self.switch_to = view_mode[0]

        ids = attrs.get('value') or []
        if not isinstance(ids, list):
            ids = [ids]

        if ids:
            if isinstance(ids[0], dict):
                current.default_data = ids
                for item in current.default_data:
                    self.default_value.append(
                        OneToMany.create(item))
                    item['id'] = 0
                ids = []
            elif isinstance(ids[0], tuple):
                [current_id[1] for current_id in ids]
        
        id = (ids or None) and ids[0]
        
        if self.name == self.source or self.name == params.source:
            if params.sort_key and ids:
                domain = current.domain or []
                domain.append(('id', 'in', ids))
                ids = rpc.RPCProxy(self.model).search(domain, current.offset, current.limit, params.sort_key + ' '+params.sort_order, current.context)
                id = ids[0]
        if current and params.source and self.name in params.source.split('/'):
            id = current.id

        id = id or None
                
        current.model = self.model
        current.id = id
        current.ids = ids
        current.view_mode = view_mode
        current.view_type = view_type
        current.domain = current.domain or []
        current.context = current.context or {}

        group_by_ctx = ''
        if self.default_get_ctx:
            ctx = dict(cherrypy.request.terp_record,
                       context=current.context,
                       active_id=self.parent_id or False)
            ctx[attrs['name']] = ids
            # XXX: parent record for O2M
            #if self.parent:
            #    ctx['parent'] = EvalEnvironment(self.parent)

            try:
                context = ctx.copy()
                ctx = expr_eval("dict(%s)" % self.default_get_ctx, context)
                ctx.update(expr_eval("dict(%s)" % attrs.get('context', '{}'), context))
                current.context.update(ctx)
            except:
                pass

            if ctx and ctx.get('group_by'):
                group_by_ctx = ctx.get('group_by')

        current.offset = current.offset or 0
        current.limit = current.limit or 50
        current.count = len(ids or [])

        # Group By for one2many list.
        if group_by_ctx:
            current.group_by_ctx = group_by_ctx
            current.domain = [('id', 'in', ids)]

        if current.view_type == 'tree' and self.readonly:
            self.editable = False

        if 'default_name' in current.context:
            del current.context['default_name']

        if self.view_type == 'tree' and pparams:
            self.editable = bool(pparams.id)

        self.screen = Screen(current, prefix=self.name, views_preloaded=view,
                             editable=self.editable, readonly=self.readonly,
                             selectable=0, nolinks=self.link, _o2m=1)
        
        self.id = id
        self.ids = ids

        if view_type == 'tree':
            self.id = None

        elif view_type == 'form':
            records_count = len(self.screen.ids or [])

            current_record = 0
            if records_count and self.screen.id in self.screen.ids:
                current_record = self.screen.ids.index(self.screen.id) + 1
                self.pager_info = _('%d of %d') % (current_record, records_count)
            else:
                self.pager_info = _('- of %d') % (records_count)