1

In odoo 17, I want the formview to only view and not edit based on the value of the field order_payment_state = done.

Instead of adding the readonly attribute to each field, I want to write a python function that inherits and modifies the get_view function to readonly the entire form view based on the field value of that formview.

Please help me do this.

1 Answer 1

1

If you want to make a form readonly, you just have to include edit="0" when declaring your form (source), e.g.

<form edit="0"> <!-- Your form here --> </form> 

Otherwise, if you really insist on using get_view to set all attributes, you should check out the hr_timesheet model's _get_view and maybe even the _apply_time_label methods (addons/hr_timesheet/model/hr_timesheet.py). The code is pretty much all there and then some. In short, I think you'd just need to modify the _get_view method to do something like:

@api.model def _get_view(self, view_id=None, view_type='form', **options): arch, view = super()._get_view(view_id, view_type, **options) # Add on conditionals or pull additional data here. E.g. can check if you only want to make certain view_types readonly. for node in arch.xpath("//field"): node.set('readonly', "1") return arch, view 

A word of caution is that if you do this in python and deploy, you're not going to be able to make the fields editable without removing said python code, as opposed to edit="0", which can be toggled ad-hoc via Odoo's debug menu, unless that's what you are going for.

Hope this helps.

Update:

After a little bit more experimenting, this is the closest I got to dynamically setting readonly attributes on all fields. The only caveat to this method is that it sets the readonly attribute to ALL fields, meaning if you have a relational field like a One2many and have defined a tree view for it within your form, you would need to edit the xpath to not select these fields, especially if you include an additional that checks for a field that is not present in the relation's model.

@api.model def _get_view(self, view_id=None, view_type='form', **options): arch, view = super()._get_view(view_id, view_type, **options) if view_type == "form": for node in arch.xpath("//field"): node.set("readonly", "id == 75") return arch, view 
Sign up to request clarification or add additional context in comments.

13 Comments

Thank you for the solution, let me ask a little more, my desired condition is that if the record has sublevel_id.level in [ 'L5.1', ​​'L7.2'] then I want to readonly that whole form, I The difficulty is: initially I wanted to get the active_id so I could get the data of sublevel_id.level, but I failed due to the fact that when I went to view the formview details of any record, it was not in self.env.context. There is no active_id, so what should I do in my case?
I think there are many ways to approach this. If you want to lock down the whole form with that condition, you can utilize the above _get_view and just add the check before setting the fields to readonly. If you want to add active_id to context, you can do so in whatever action you use to access your form by including a <field name="context"> and try adding the fields you need there.
If you could also elaborate how you are accessing this record, it would be more helpful, e.g. clicking on the record from a Tree view or from a button.
I clicked the record from the tree view, can you edit the get_view function code so I can see, based on the condition sublevel_id.level in ['L5.1', ​​'L7.2'], I got tried but failed
I don't have enough reputation to comment on your post so I'll do it here. Please post your error logs as well otherwise its impossible to diagnose. As per your question tag, you're using Odoo 17 where readonly no longer accepts domains, it just accepts a normal python statement so that could be a cause
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.