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

OPENERP 构建动态视图的更多相关文章

  1. openerp创建动态视图-fields_view_get

    openerp的视图结构是以XML的格式存放于ir.ui.view表中,属于静态格式,设计之后就固定, 但可以通过在model中重写fields_view_get函数,在视图加载时修改arch属性,动 ...

  2. 使用Expression Tree构建动态LINQ查询

    这篇文章介绍一个有意思的话题,也是经常被人问到的:如何构建动态LINQ查询?所谓动态,主要的意思在于查询的条件可以随机组合,动态添加,而不是固定的写法.这个在很多系统开发过程中是非常有用的. 我这里给 ...

  3. 面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序

    面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序 Ajax 为更好的 Web 应用程序铺平了道路 在 Web 应用程序开发中,页面重载循环是最大的一个使用障碍,对于 Java™ ...

  4. oracle动态视图v$,v_$,gv$,gv_$与x$之间的关系

    前言:在oracle运维的过程中,经常会使用到一些以V$开头的动态视图,比如V$session, 有一次偶然看到有人用V_$session, 初以为别人写错了,没想到desc v_$session以后 ...

  5. LNMP构建动态网站WordPress

    LNMP构建动态网站wordpress 一.部署LNMP架构 1.安装nginx #配置nginx源 cat>/etc/yum.repos.d/nginx.repo<<-EOF [N ...

  6. 使用 FirewallD 构建动态防火墙

    使用 FirewallD 构建动态防火墙 FirewallD 提供了支持网络/防火墙区域(zone)定义网络链接以及接口安全等级的动态防火墙管理工具.它支持 IPv4, IPv6 防火墙设置以及以太网 ...

  7. <十五>UML核心视图动态视图之活动图

    一:动态视图 --->动态视图是描述事物动态行为的. --->需要注意的是:动态视图不能够独立存在,它必需特指一个静态视图活uml元素,说明在静态视图规定的事物结构下它们的动态行为. -- ...

  8. LESS是一个CSS预处理器,跨浏览器友好,提供诸如变量,函数, mixins 和操作等功能,可以构建动态CSS

    什么是LESS? LESS是一个CSS预处理器,可以为网站启用可自定义,可管理和可重用的样式表. LESS是一种动态样式表语言,扩展了CSS的功能. LESS也是跨浏览器友好. CSS预处理器是一种脚 ...

  9. 关于phoenix构建hbase视图,更新hbase表后,视图表是否更新的验证

    1:创建表 create 'MY_TABLE', 'CF1','CF2' 2:在hbase上插入一条数据 put ' ,'CF1:V1', 'uwo1' 3:在phoenix上创建视图 create ...

随机推荐

  1. [HDU1290]献给杭电五十周年校庆的礼物

    [HDU1290]献给杭电五十周年校庆的礼物 题目大意: 问\(n(n\le1000)\)个平面能够将一个三维空间分成几部分. 思路: 公式\(\frac{n^3+5n+6}6\). 源代码: #in ...

  2. VK Cup 2016 - Qualification Round 2 D. Three-dimensional Turtle Super Computer 暴力

    D. Three-dimensional Turtle Super Computer 题目连接: http://www.codeforces.com/contest/638/problem/D Des ...

  3. CROC 2016 - Elimination Round (Rated Unofficial Edition) D. Robot Rapping Results Report 二分+拓扑排序

    D. Robot Rapping Results Report 题目连接: http://www.codeforces.com/contest/655/problem/D Description Wh ...

  4. Map中keySet和entrySet的区别

    在Map集合中 values():方法是获取集合中的所有的值----没有键,没有对应关系, KeySet():将Map中所有的键存入到set集合中.因为set具备迭代器.所有可以迭代方式取出所有的键, ...

  5. HttpURLConnection与 HttpClient 区别/性能测试对比

    HttpClient是个开源框架,封装了访问http的请求头,参数,内容体,响应等等, HttpURLConnection是java的标准类,什么都没封装,用起来太原始,不方便 HttpClient实 ...

  6. 几种OutOfMemoryError

    JAVA虚拟机OutOfMemoryError主要包括以下四类:java.lang.OutOfMemoryError: Java heap spacejava.lang.OutOfMemoryErro ...

  7. UIColor和 同 CIColor 与 CGColor 之间的联系、转换

    1. 利用UIColor展现 #F6F6F6 这个传统的颜色 #F6F6F6 为一个 16 进制表示的RPG颜色,所以,需要先转换成 10进制,其中 F6 - 240,F6 -  240 ,F6 - ...

  8. 升/降压转换器 (Buck-boost)

    升/降压转换器 (Buck-boost) 当输入电压是变动的,有时比输出电压高.有时却比较低时(例如放电中的电池),升/降压转换器 (Buck-boost) 是最佳的电源解决方案. 升/降压转换器 ( ...

  9. 关于U盘启动操作系统《30天自制操作系统》

    原本的启动是从img启动的,并且这个img是用FAT12文件系统进行格式化的(详细去搜索FAT12文件格式,这里给大家推荐一篇http://www.doc88.com/p-646605198560.h ...

  10. Unity3d面试6

    1,如何避免点击UI按钮时穿透,同时触发了相同位置场景模型的点击事件的情况?(NGUI)1,如何避免点击UI按钮时穿透,同时触发了相同位置场景模型的点击事件的情况?(NGUI 判断 是否点击到UI) ...