首页 > 代码库 > OPENERP 构建动态视图

OPENERP 构建动态视图

来自:http://shine-it.net/index.php/topic,16142.0.html

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

# -*- coding: utf-8 -*-from openerp.osv import osv,fieldsfrom lxml import etreefrom openerp import toolsfrom openerp.tools import to_xmlclass 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
上述代码用户可以自己定义问卷题目及题目类型。通过fields_view_get()画出view,然后把动态构建的字段及其值通过重写create() 把数据存储到另外一个表里。这里用的是一个text字段把create返回的值直接存储起来的。当需要查看保存过的数据时,通过重写read()整理成需要的数据格式返回。