OPENERP 构建动态视图



  • 在openerp展示界面通常是通过定义class的view(xml文件)来实现的。
    有时这种方法不能支持用户自定义字段的需求,于是就可以通过重写fields_view_get()、 read()来实现。
    实例代码

    [code]

    # -- coding: utf-8 --
    from openerp.osv import osv,fields
    from lxml import etree
    from openerp import tools
    from openerp.tools import to_xml




    class AnalysisQuestionnaireType(osv.osv):
        name = 'analysis.questionnaire.type'
        description = '问卷类型'
        columns = {
            'name': fields.char('名称', size=125, required=True),
            'analysis_set': fields.many2many('analysis.title.set', id1='analysis_questionnaire_type_id',
                                            id2='analysis_title_set_id', string='主题'),
        }




    class AnalysisTitleSet(osv.osv):
        name = "analysis.title.set"
        description = "主题"
        columns = {
            "name": fields.char(string="名称", size=125, required=True,),
            'analysis_questionnaire_type': fields.many2many('analysis.questionnaire.type',
                                                            id1='analysis_title_set_id',
                                                            id2='analysis_questionnaire_type_id',
                                                            string='问卷类型'),
            "analysis_title": fields.one2many('analysis.title', 'set', '题目'),
        }




    class AnalysisTitle(osv.osv):
        name = "analysis.title"
        description = "题目"
        columns = {
            "name": fields.char(string="名称", size=125, required=True),
            "note": fields.text("描述"),
            "set": fields.many2one("analysis.title.set", string="主题", required=True),
            'type': fields.selection([('multiple_choice_only_one_ans', '单项选择'),
                                      ('multiple_choice_multiple_ans', '多项选择'),
                                      ('matrix_of_choices_only_one_ans', '单选组合'),
                                      ('single_textbox', '单行文本框'),
                                      ('multiple_textbox', '多个单行文本框'),
                                      ('comment', '多行文本框'),
                                      ('date', '日期框'),
                                      ('date_and_time', '日期时间框'),
                                      ('descriptive_text', '描述性文本'),
                                      ('attachment', '附件'),
                                      ('image', '图片'),
                                      ], '题目类型',  required=1,),
            'is_require_answer': fields.boolean('必填项'),
            'option_id': fields.one2many('analysis.title.option', 'title_id', '备选答案'),
            'column_heading_ids': fields.one2many('analysis.title.column.heading', 'title_id', '标题'),
            'descriptive_text': fields.text('描述文本'),
        }




    class AnalysisTitleOption(osv.osv):
        name = 'analysis.title.option'
        description = '答案选项'
        columns = {
            'title_id': fields.many2one('analysis.title', '题目', ondelete='cascade'),
            'option': fields.char('答案选项', size=128, required=True),
            'type': fields.selection([('char', '字符型'),
                                    ('date', '日期'),
                                    ('datetime', '日期时间型'),
                                    ('integer', '整数型'),
                                    ('float', '小数型'),
                                    ('selection', '选择型')],
                                    '答案类型',
                                    required=True),


        }




    class AnalysisTitleColumnHeading(osv.osv):
        name = 'analysis.title.column.heading'
        description = '选项标题'
        columns = {
            'name': fields.char('选项标题', size=128, required=True),
            'title_id': fields.many2one('analysis.title', '题目', ondelete='cascade'),
        }




    class AnalysisAnswer(osv.osv):
        name = 'analysis.answer'
        description = '答案'
        columns = {
            'analysis_questionnaire': fields.many2one('analysis.questionnaire', '问卷'),
            'value': fields.text('值')
        }




    class AnalysisQuestionnaire(osv.osv):
        name = 'analysis.questionnaire'
        description = '分析问卷'


        columns = {
            "name": fields.char(string='名称', size=125, required=True),
            'type': fields.many2one('analysis.questionnaire.type', string='类型', required=True),
            'title': fields.one2many('analysis.answer', "analysis_questionnaire", "答案"),
        }


        def default_get(self, cr, uid, fields_list, context=None):
            default = super(AnalysisQuestionnaire, self).default_get(cr, uid, fields_list, context=context)
            con = context.get('type')
            default['type'] = con
            return default


        def view_init(self, cr, uid, fields_list, context=None):
            pass


        def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False,):
            if context is None:
                context = {}
            result = super(AnalysisQuestionnaire, self).fields_view_get(cr, uid, view_id,
                                                                        view_type=view_type, context=context,
                                                                        toolbar=toolbar, submenu=submenu)
            if view_type == 'form' and context.has_key('type'):
                view = etree.fromstring(result['arch'])
                fields = result['fields']
                print etree.tostring(view)
                notebook = etree.SubElement(view, 'notebook')
                sets = self.pool.get('analysis.questionnaire.type').browse(cr, uid, context['type']).analysis_set
                q_no = 0
                for set in sets:
                    page = etree.SubElement(notebook, 'page', string=set.name)
                    for title in set.analysis_title:
                        q_no += 1
                        etree.SubElement(page, 'newline')
                        if title.is_require_answer:
                            etree.SubElement(page, 'separator', {'string': '*'+tools.ustr(q_no)+'.'+tools.ustr(title.name)})
                        else:
                            etree.SubElement(page, 'separator', {'string': tools.ustr(q_no)+'.'+tools.ustr(title.name)})


                        if title.type == 'multiple_choice_only_one_ans':
                            parent = etree.SubElement(page, 'group')
                            selection = []
                            for option in title.option_id:
                                selection.append((tools.ustr(option.id), option.option))
                            fields['title'+'
    '+tools.ustr(title.id)+'selection'] = {'type': 'selection',
                                                                                    'selection': selection,
                                                                                    'name': title.name}
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'selection'})
                        elif title.type == 'multiple_choice_multiple_ans':
                            parent = etree.SubElement(page, 'group', {'col': '4', 'colspan': '4'})
                            for option in title.option_id:
                                etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'option'+'
    '
                                                                          + tools.ustr(option.id)})
                                fields['title'+'
    '+tools.ustr(title.id)+'-'+'option'+'
    '
                                      + tools.ustr(option.id)] = {'type': 'boolean', 'string': option.option}
                        elif title.type == 'matrix_of_choices_only_one_ans':
                            parent = etree.SubElement(page, 'group', {'col': '2', 'colspan': '2'})
                            selection = []
                            for option in title.option_id:
                                selection.append((tools.ustr(option.id), option.option))
                            for col in title.column_heading_ids:
                                etree.SubElement(parent, 'newline')
                                etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                                                          + tools.ustr(col.id),
                                                                  })
                                fields['title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                      + tools.ustr(col.id)] = {'type': 'selection', 'selection': selection}
                        elif title.type == 'single_textbox':
                            parent = etree.SubElement(page, 'group',)
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id) + "single",
                                                              'nolabel': "1",
                                                              'colspan': "4"})
                            fields['title'+'
    '+tools.ustr(title.id) + "single"] = {'type': 'char', 'size': 255}
                        elif title.type == 'multiple_textbox':
                            parent = etree.SubElement(page, 'group', {'col': '4', 'colspan': '4'})
                            for col in title.column_heading_ids:
                                fields['title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '+tools.ustr(col.id)] = {'type': 'char',
                                                                                                            'size': 255}
                                etree.SubElement(parent, 'field', {'width': '300',
                                                                  'colspan': '1',
                                                                  'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                                                          + tools.ustr(col.id)})
                        elif title.type == 'comment':
                            parent = etree.SubElement(page, 'group')
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id) + "comment",
                                                              'nolabel': "1",
                                                              'colspan': "4"})
                            fields['title'+'
    '+tools.ustr(title.id) + "comment"] = {'type': 'text'}
                        elif title.type == 'date':
                            parent = etree.SubElement(page, 'group', {'col': '4', 'colspan': '4'})
                            for col in title.column_heading_ids:
                                fields['title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '+tools.ustr(col.id)] = {'type': 'date'}
                                etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                                                          + tools.ustr(col.id)})
                        elif title.type == 'date_and_time':
                            parent = etree.SubElement(page, 'group', {'col': '4', 'colspan': '4'})
                            for col in title.column_heading_ids:
                                fields['title'+'
    '+tools.ustr(title.id)+'-'
                                      + 'col'+'
    '+tools.ustr(col.id)] = {'type': 'datetime'}
                                etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                                                          + tools.ustr(col.id)})
                        elif title.type == 'attachment':
                            parent = etree.SubElement(page, 'group',)
                            fields['title'+'
    '+tools.ustr(title.id)+'attachment'] = {'type': 'binary'}
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'attachment'})
                        elif title.type == 'descriptive_text':
                            parent = etree.SubElement(page, 'group')
                            if title.descriptive_text:
                                for que_test in title.descriptive_text.split('\n'):
                                    etree.SubElement(parent, 'label', {'string': to_xml(tools.ustr(que_test)),
                                                                      'align': "0.0"})
                        elif title.type == 'image':
                            parent = etree.SubElement(page, 'group',)
                            fields['title'+'
    '+tools.ustr(title.id)+'image'] = {'type': 'binary'}
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'_image',
                                                              'widget': 'image'})
                result['arch'] = etree.tostring(view)
            return result


        def create(self, cr, uid, vals, context=None):
            answer_obj = self.pool.get("analysis.answer")
            questionnaire_vals = {'name': vals.get('name'), 'type': vals.get('type')}
            vals.pop('name', "not name")
            vals.pop('type', 'not type')
            answer_vals = {}
            questionnaire_id = super(AnalysisQuestionnaire, self).create(cr, uid, questionnaire_vals, context=context)
            answer_vals['analysis_questionnaire'] = questionnaire_id
            answer_vals['value'] = vals
            answer_obj.create(cr, uid, answer_vals, context=context)
            return questionnaire_id


        def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
            result = super(AnalysisQuestionnaire, self).read(cr, user, ids, fields=fields, context=context, load=load)
            answer_obj = self.pool.get('analysis.answer')
            i = 0
            while i < len(result):
                answer_list = answer_obj.search(cr, user, [('analysis_questionnaire', '=', result['id'])])
                if answer_list:
                    val = eval(answer_obj.read(cr, user, answer_list, ['value'], context=context)[0]['value'])
                    result.update(val)
                i += 1
            return result
    [/code][i]
    [color=rgb(69, 69, 69)][font=tahoma][size=14px]上述代码用户可以自己定义问卷题目及题目类型。通过fields_view_get()画出view,然后把动态构建的字段及其值通过重写create()把数据存储到另外一个表里。这里用的是一个text字段把create返回的值直接存储起来的。当需要查看保存过的数据时,通过重写read()整理成需要的数据格式返回。[/size][/font][/color][/i]



  • 在openerp展示界面通常是通过定义class的view(xml文件)来实现的。
    有时这种方法不能支持用户自定义字段的需求,于是就可以通过重写fields_view_get()、 read()来实现。
    实例代码

    [code]

    # -- coding: utf-8 --
    from openerp.osv import osv,fields
    from lxml import etree
    from openerp import tools
    from openerp.tools import to_xml




    class AnalysisQuestionnaireType(osv.osv):
        name = 'analysis.questionnaire.type'
        description = '问卷类型'
        columns = {
            'name': fields.char('名称', size=125, required=True),
            'analysis_set': fields.many2many('analysis.title.set', id1='analysis_questionnaire_type_id',
                                            id2='analysis_title_set_id', string='主题'),
        }




    class AnalysisTitleSet(osv.osv):
        name = "analysis.title.set"
        description = "主题"
        columns = {
            "name": fields.char(string="名称", size=125, required=True,),
            'analysis_questionnaire_type': fields.many2many('analysis.questionnaire.type',
                                                            id1='analysis_title_set_id',
                                                            id2='analysis_questionnaire_type_id',
                                                            string='问卷类型'),
            "analysis_title": fields.one2many('analysis.title', 'set', '题目'),
        }




    class AnalysisTitle(osv.osv):
        name = "analysis.title"
        description = "题目"
        columns = {
            "name": fields.char(string="名称", size=125, required=True),
            "note": fields.text("描述"),
            "set": fields.many2one("analysis.title.set", string="主题", required=True),
            'type': fields.selection([('multiple_choice_only_one_ans', '单项选择'),
                                      ('multiple_choice_multiple_ans', '多项选择'),
                                      ('matrix_of_choices_only_one_ans', '单选组合'),
                                      ('single_textbox', '单行文本框'),
                                      ('multiple_textbox', '多个单行文本框'),
                                      ('comment', '多行文本框'),
                                      ('date', '日期框'),
                                      ('date_and_time', '日期时间框'),
                                      ('descriptive_text', '描述性文本'),
                                      ('attachment', '附件'),
                                      ('image', '图片'),
                                      ], '题目类型',  required=1,),
            'is_require_answer': fields.boolean('必填项'),
            'option_id': fields.one2many('analysis.title.option', 'title_id', '备选答案'),
            'column_heading_ids': fields.one2many('analysis.title.column.heading', 'title_id', '标题'),
            'descriptive_text': fields.text('描述文本'),
        }




    class AnalysisTitleOption(osv.osv):
        name = 'analysis.title.option'
        description = '答案选项'
        columns = {
            'title_id': fields.many2one('analysis.title', '题目', ondelete='cascade'),
            'option': fields.char('答案选项', size=128, required=True),
            'type': fields.selection([('char', '字符型'),
                                    ('date', '日期'),
                                    ('datetime', '日期时间型'),
                                    ('integer', '整数型'),
                                    ('float', '小数型'),
                                    ('selection', '选择型')],
                                    '答案类型',
                                    required=True),


        }




    class AnalysisTitleColumnHeading(osv.osv):
        name = 'analysis.title.column.heading'
        description = '选项标题'
        columns = {
            'name': fields.char('选项标题', size=128, required=True),
            'title_id': fields.many2one('analysis.title', '题目', ondelete='cascade'),
        }




    class AnalysisAnswer(osv.osv):
        name = 'analysis.answer'
        description = '答案'
        columns = {
            'analysis_questionnaire': fields.many2one('analysis.questionnaire', '问卷'),
            'value': fields.text('值')
        }




    class AnalysisQuestionnaire(osv.osv):
        name = 'analysis.questionnaire'
        description = '分析问卷'


        columns = {
            "name": fields.char(string='名称', size=125, required=True),
            'type': fields.many2one('analysis.questionnaire.type', string='类型', required=True),
            'title': fields.one2many('analysis.answer', "analysis_questionnaire", "答案"),
        }


        def default_get(self, cr, uid, fields_list, context=None):
            default = super(AnalysisQuestionnaire, self).default_get(cr, uid, fields_list, context=context)
            con = context.get('type')
            default['type'] = con
            return default


        def view_init(self, cr, uid, fields_list, context=None):
            pass


        def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False,):
            if context is None:
                context = {}
            result = super(AnalysisQuestionnaire, self).fields_view_get(cr, uid, view_id,
                                                                        view_type=view_type, context=context,
                                                                        toolbar=toolbar, submenu=submenu)
            if view_type == 'form' and context.has_key('type'):
                view = etree.fromstring(result['arch'])
                fields = result['fields']
                print etree.tostring(view)
                notebook = etree.SubElement(view, 'notebook')
                sets = self.pool.get('analysis.questionnaire.type').browse(cr, uid, context['type']).analysis_set
                q_no = 0
                for set in sets:
                    page = etree.SubElement(notebook, 'page', string=set.name)
                    for title in set.analysis_title:
                        q_no += 1
                        etree.SubElement(page, 'newline')
                        if title.is_require_answer:
                            etree.SubElement(page, 'separator', {'string': '*'+tools.ustr(q_no)+'.'+tools.ustr(title.name)})
                        else:
                            etree.SubElement(page, 'separator', {'string': tools.ustr(q_no)+'.'+tools.ustr(title.name)})


                        if title.type == 'multiple_choice_only_one_ans':
                            parent = etree.SubElement(page, 'group')
                            selection = []
                            for option in title.option_id:
                                selection.append((tools.ustr(option.id), option.option))
                            fields['title'+'
    '+tools.ustr(title.id)+'selection'] = {'type': 'selection',
                                                                                    'selection': selection,
                                                                                    'name': title.name}
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'selection'})
                        elif title.type == 'multiple_choice_multiple_ans':
                            parent = etree.SubElement(page, 'group', {'col': '4', 'colspan': '4'})
                            for option in title.option_id:
                                etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'option'+'
    '
                                                                          + tools.ustr(option.id)})
                                fields['title'+'
    '+tools.ustr(title.id)+'-'+'option'+'
    '
                                      + tools.ustr(option.id)] = {'type': 'boolean', 'string': option.option}
                        elif title.type == 'matrix_of_choices_only_one_ans':
                            parent = etree.SubElement(page, 'group', {'col': '2', 'colspan': '2'})
                            selection = []
                            for option in title.option_id:
                                selection.append((tools.ustr(option.id), option.option))
                            for col in title.column_heading_ids:
                                etree.SubElement(parent, 'newline')
                                etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                                                          + tools.ustr(col.id),
                                                                  })
                                fields['title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                      + tools.ustr(col.id)] = {'type': 'selection', 'selection': selection}
                        elif title.type == 'single_textbox':
                            parent = etree.SubElement(page, 'group',)
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id) + "single",
                                                              'nolabel': "1",
                                                              'colspan': "4"})
                            fields['title'+'
    '+tools.ustr(title.id) + "single"] = {'type': 'char', 'size': 255}
                        elif title.type == 'multiple_textbox':
                            parent = etree.SubElement(page, 'group', {'col': '4', 'colspan': '4'})
                            for col in title.column_heading_ids:
                                fields['title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '+tools.ustr(col.id)] = {'type': 'char',
                                                                                                            'size': 255}
                                etree.SubElement(parent, 'field', {'width': '300',
                                                                  'colspan': '1',
                                                                  'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                                                          + tools.ustr(col.id)})
                        elif title.type == 'comment':
                            parent = etree.SubElement(page, 'group')
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id) + "comment",
                                                              'nolabel': "1",
                                                              'colspan': "4"})
                            fields['title'+'
    '+tools.ustr(title.id) + "comment"] = {'type': 'text'}
                        elif title.type == 'date':
                            parent = etree.SubElement(page, 'group', {'col': '4', 'colspan': '4'})
                            for col in title.column_heading_ids:
                                fields['title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '+tools.ustr(col.id)] = {'type': 'date'}
                                etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                                                          + tools.ustr(col.id)})
                        elif title.type == 'date_and_time':
                            parent = etree.SubElement(page, 'group', {'col': '4', 'colspan': '4'})
                            for col in title.column_heading_ids:
                                fields['title'+'
    '+tools.ustr(title.id)+'-'
                                      + 'col'+'
    '+tools.ustr(col.id)] = {'type': 'datetime'}
                                etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'-'+'col'+'
    '
                                                                          + tools.ustr(col.id)})
                        elif title.type == 'attachment':
                            parent = etree.SubElement(page, 'group',)
                            fields['title'+'
    '+tools.ustr(title.id)+'attachment'] = {'type': 'binary'}
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'attachment'})
                        elif title.type == 'descriptive_text':
                            parent = etree.SubElement(page, 'group')
                            if title.descriptive_text:
                                for que_test in title.descriptive_text.split('\n'):
                                    etree.SubElement(parent, 'label', {'string': to_xml(tools.ustr(que_test)),
                                                                      'align': "0.0"})
                        elif title.type == 'image':
                            parent = etree.SubElement(page, 'group',)
                            fields['title'+'
    '+tools.ustr(title.id)+'image'] = {'type': 'binary'}
                            etree.SubElement(parent, 'field', {'name': 'title'+'
    '+tools.ustr(title.id)+'_image',
                                                              'widget': 'image'})
                result['arch'] = etree.tostring(view)
            return result


        def create(self, cr, uid, vals, context=None):
            answer_obj = self.pool.get("analysis.answer")
            questionnaire_vals = {'name': vals.get('name'), 'type': vals.get('type')}
            vals.pop('name', "not name")
            vals.pop('type', 'not type')
            answer_vals = {}
            questionnaire_id = super(AnalysisQuestionnaire, self).create(cr, uid, questionnaire_vals, context=context)
            answer_vals['analysis_questionnaire'] = questionnaire_id
            answer_vals['value'] = vals
            answer_obj.create(cr, uid, answer_vals, context=context)
            return questionnaire_id


        def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
            result = super(AnalysisQuestionnaire, self).read(cr, user, ids, fields=fields, context=context, load=load)
            answer_obj = self.pool.get('analysis.answer')
            i = 0
            while i < len(result):
                answer_list = answer_obj.search(cr, user, [('analysis_questionnaire', '=', result['id'])])
                if answer_list:
                    val = eval(answer_obj.read(cr, user, answer_list, ['value'], context=context)[0]['value'])
                    result.update(val)
                i += 1
            return result
    [/code][i]
    [color=rgb(69, 69, 69)][font=tahoma][size=14px]上述代码用户可以自己定义问卷题目及题目类型。通过fields_view_get()画出view,然后把动态构建的字段及其值通过重写create()把数据存储到另外一个表里。这里用的是一个text字段把create返回的值直接存储起来的。当需要查看保存过的数据时,通过重写read()整理成需要的数据格式返回。[/size][/font][/color][/i]



  • good  idea 又学了一招



  • 学习了!



  • qdfulee你好!感谢分享的代码,如若方便,可否将整体的代码贴出来,或打包发给我【lykiao@sina.com】,菜鸟一枚,想在调试的过程中加以学习理解。多谢了~


登录后回复
 

与 Odoo 中文社区 的连接断开,我们正在尝试重连,请耐心等待