I do not want my user group to archive records when my user group has the create and write rights. For kanban view "archivable='false'" is an option but for the list view, this does not exist. How can I remove or don't show this button for that user group?
Add groups='your_module.your_group' to your active field.
This solved my problem.
You can dynamically hide for the specific user with fields_view_get method.
#api.model
def fields_view_get(self, view_id=None, view_type='form', toolbar=False,
submenu=False):
res = super(Classname, self).fields_view_get(
view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
if view_type == 'tree' and self.user_has_groups('Your Group') and Other Condition:
doc = etree.XML(res['arch'])
for node in doc.xpath("//your button"):
node.set('modifiers', json.dumps({'invisible': 1}))
res['arch'] = etree.tostring(doc, encoding='unicode')
return res
Thanks
You can use the group option in button menu like this
<button name="order_confirm" states="draft" string="Confirm Order" groups="xml id( group)"/>
This will show that particular button for specific group only..
Related
I am building a app using flask-appbuilder and I have an action that runs a function and I want to update the row in the table with the output of function. Can't work out how to do it. Any help? Thanks
#action("prospect", "Prospect", "off we go", "fa-rocket")
def prospect(self, items):
if isinstance(items, list):
for a in items:
out = self.myfunction(a.name)
#Need to update the table with output
#anyideas?
self.update_redirect()
else:
print "nothing"
return redirect(self.get_redirect())
I'm assuming this is a View that is related to a model. If this is the case, you relate the model to the view using Flask-AppBuilder SQLAInterface class.
This class allows you to interact with the item in the database.
This class has an 'edit' method that let's you update the item.
Let's say your model is like the one below:
class Contact(Model):
id = Column(Integer, primary_key=True)
name = Column(String(50), unique = True, nullable=False)
Let's say you want to implement an action that capiltalizes the contact name, and you want to be able to do it on the the 'List' and 'Show' views. This is one way to do it:
class ContactView(ModelView):
datamodel = SQLAInterface(Contact)
#action("capitalize",
"Capitalize name",
"Do you really want to capitalize the name?")
def capitalize(self, contacts):
if isinstance(contacts, list):
for contact in contacts:
contact.name = contact.name.capitalize()
self.datamodel.edit(contact)
self.update_redirect()
else:
contacts.name = contacts.name.capitalize()
self.datamodel.edit(contacts)
return redirect(self.get_redirect())
You can check other SQLAInterface methods here.
I have created a custom header menu called 'HM-1'
And i have created a Menu called 'Menu 1'
Inside 'Menu 1' i have 3 fields created, called field_1 fileds_2 filed_3.
I created a 'User' and i have two users now
1. Admin
2. User
My question is 'How to make one field(field_3) 'User' and 'Admin' editable in Openerp-7'
Remaining fields in 'User' should be readonly only field_3 should be editable.
How to do this?
The first thing that come into my mind is to override fields_view_get and change the readonly and modifiers attribute of field_1 and field_2 based on groups of self.env.user. Of course you need to assign User to a specific group, different to the one of Admin.
class example_class(models.Model):
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(example_class, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
group = self.pool['ir.model.data'].xmlid_to_object(cr, uid, 'your_group', raise_if_not_found=True, context=context)
if view_type == 'form' and group in self.env.user.groups_id:
doc = etree.XML(res['arch'])
#this for cycle must be repeated for each field you need to make readonly
for node in doc.xpath("//field[#name='field_2']"):
if 'modifiers' in node.attrib:
text = node.attrib['modifiers']
j = json.loads(text)
j['readonly'] = '1'
else:
j = {'readonly': '1'}
node.attrib['modifiers'] = json.dumps(j)
res['arch'] = etree.tostring(doc)
return res
What are the key roles of active_ids and active_id in development ?
I want to know Advantages and Limitations of that functionality provided by odoo.
In certain case what we can do if I can not get the active_ids in context while opening wizard from other model's list view ?
Here is the action which I used to open my wizard from list view of product.product model.
<act_window name="Calculate Product Price"
res_model="wizard.main"
src_model="product.product"
view_mode="form"
view_type="form"
target="current"
multi="True"
key2="client_action_multi"
id="action_product_price_calculator_ept"
view_id="view_product_calculator_wizard"/>
Here is my python code to get active ids.
#api.model
def default_get(self, fields):
context = self.env.context
res = super(wizard_main, self).default_get(fields)
product_ids = context.get('active_ids',[])
if not product_ids:
return res
#### few more lines will be added here
return res
In Odoo/Openerp i created a kanban view to display some data. Now i managed to change this view with the fields_view_get based on context data.
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
if context is None:
context = {}
res = super(esfyt_subscription_template,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
if context.get('partner_id', False):
partner_id = context.get('partner_id', False)
doc = etree.XML(res['arch'])
if view_type == 'kanban':
for node in doc.xpath("//div[#class='oe_module_vignette']"):
new_addition = etree.SubElement(node, 'button', {'string' : 'Subscribe', 'type' : 'object', 'name' : 'action_subscribe'})
new_addition.text = 'Subscribe'
res['arch'] = etree.tostring(doc)
return res
But i need to do the same with the data. i need to limit some data based on context, o certain models(or rows) arent loaded in the view.
How can i do that?
To filter records based on the context, you have to override the search() method
To filter data based on the context, you have to override the read()/browse() methods
What I need to do is access values of the columns in a certain module before it's saved.
For example, if we have a module defined like this:
_columns = {
'name': fields.char('Department Name', size=64, required=True),
'complete_name': fields.function(_dept_name_get_fnc, type="char", string='Name'),
'parent_id': fields.many2one('hr.department', 'Parent Department', select=True),
'child_ids': fields.one2many('hr.department', 'parent_id', 'Child Departments'),
'note': fields.text('Note'),
}
All those columns are represented by controls such as textbox, combobox, checkbox, etc.
When we open the form view in the create mode, a new record is being created but not saved and won't take an id in the database until we click (save).
The question is how to access the values of those fields (controls) before they are saved and before the current record takes a new id.
I know about self.browse and self.search but they need an ID which is not available because the record is not saved yet.
Also, can we assign a global variable that could be accessed from any class in the module (a session variable in web-development terms)?
Better override create method, and use the way you want. Try this in you object, Its an example,
def create(self, cr, uid, vals, context=None):
if vals.get('name','/')=='/':
vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'sale.order') or '/'
return super(sale_order, self).create(cr, uid, vals, context=context)
likewise you can do your changes from here itself, see the value of "vals" and "context",
this would be helpful to you.
If you want to access this field than you need to override the create method of orm. For Example:
def create(self, cr, uid, vals, context=None):
name = vals.get('name')
complete_name = vals.get('complete_name') # like all others field if one2many field comes than this field access using for loop.
vals.update({'your_field_name': your_value_what_you_want_to_update_before_creating})
#vals.update({'name': 'Your Good Name'})
return super(your_class_name, self).create(cr, uid, vals, context)
def write(self, cr, uid, ids, vals, context=None):
print "\n\n\nCurrent Values =>", vals
name = vals.get('name')
print "\nCurrent Name => ", name
complete_name = vals.get('complete_name') # like all others field if one2many field comes than this field access using for loop.
#do all calculation as you want and store in local variable and that variable pass as a value. for example.
name = 'Your Good Name'
vals.update({'name': name})
print "\n\nUpdated Values => ", vals
return super(your_class_name, self).write(cr, uid, ids, vals, context)
Hope this will help you.