Get Parent Model ID from Child during New Child Creation

Hi,

I have a code as below in a parent model (Project):

    @classmethod
    def __setup__(cls):
        super().__setup__()
        cls.proj_phase.selection = cls._get_phases(cls)
        cls.proj_type.selection = cls._get_proj_types(cls)
        cls._buttons.update({
            'open_milestone_wizard_form': {
                'readonly': Eval('id', -1) < 0,
                'invisible': Eval('proj_type') != 'MILESTONES'
            }
        })

    @classmethod
    @ModelView.button_action('afx_project.act_project_milestone_input_view_form')
    def open_milestone_wizard_form(cls, objects):
        pass

When user click the button, the wizard popped-up, and I can retrieve Parent’s model ID using project = self.records[0] based on this solution, like below:


    def default_start(self, fields):
        projects = self.records #--- THIS WHERE I GOT PARENT'S MODEL ID ----
        if projects:
            days = 0
            project = projects[0]
            

I try to do the same using the default PLUS button see below screenshot

but I cannot get the parent model ID:

class ProjectMilestone(ModelSQL, ModelView):
    'Project Milestone'
    __name__ = 'afx.project.milestone'

    project = fields.Many2One('afx.project', "Project", required=True, ondelete='CASCADE')

    proj_name = fields.Function(fields.Char('Project Name', readonly=True), 'get_proj_name')
    proj_start = fields.Function(fields.Date('Project Start Date', readonly=True), 'get_proj_start')
    proj_end = fields.Function(fields.Date('Project End Date', readonly=True), 'get_proj_end')
    proj_duration = fields.Function(fields.Integer('Project Duration (days)', readonly=True), 'get_proj_duration')
    proj_remaining_days = fields.Function(fields.Integer("Project's Remaining (days)", readonly=True), 'calc_proj_remaining_days')
    
    def get_proj_name(self, name):
        return self.project.proj_name
    
    def get_proj_start(self, name):
        return self.project.start_date
    
    def get_proj_end(self, name):
        return self.project.end_date
    
    def get_proj_duration(self, name):
        return self.project.proj_duration

Those methods to get projec’s data are all failed, meanwhile in the Front end, you don’t have option to select a Parent. How can I get the parent model’s data, like what I do if I am using Wizard?

Wizard can shows Project’s data as seen in below screenshot:

Note: if this is impossible, maybe the best solution is to force user to use button that triggers Wizard Form to popup.. but I need to disable PLUS button but still enable user to open an update form.

Regards
Bromo

getter method of Function fields work only on stored data in the database. If you want fields to react when edited in the client, you must use ˋon_changemethods. The bonus point is that you can use the same method asgetterandon_change_with`.

Hi @ced, actually I just want the user to have the same user experience if they use Wizard form. So is there a way to just disable the PLUS button without setting the tree to ‘readonly’ because I need the user to be able to edit the child using a form after double-clicking the record?

Bromo

No because this is not how Tryton is designed.
Wizards are not substitution to form.

on_change method would work only on editing existing child data. The requirement is to get the parent ID when a new child form pops up after clicking the PLUS button. The reason is simple: we want to show some data from the Parent object in the new child form.

I wonder if there is a way around this, or at least hiding the Plus button to prevent users from clicking the Plus button following their normal UX in Tryton.
I believe this question has been asked before.

Or since the child form is like below:

<form>
    <label name="project"/>
    <field name="project"/>
    <newline/>
    <label name="month"/>
    <field name="month"/>
    <label name="year"/>
    <field name="year"/>
    <label name="quot_desc"/>
    <field name="quot_desc"/>
    <label name="purc_desc"/>
    <field name="purc_desc"/>
    <label name="work_days"/>
    <field name="work_days"/>
    <label name="base_cost"/>
    <field name="base_cost"/>
    <label name="purchase_cost"/>
    <field name="purchase_cost"/>
    <label name="billed"/>
    <field name="billed"/>
</form>

How to make field name=“project” visible so I can choose the project in a poped up form after clicking Plus button. At least user can choose the Project (as parent) and the form can show required data from Parent object.

The client set the “parent” field when creating a new record in a One2Many.

No it is impossible because they can be only one valid value so there is no choice.

You said: The client set the “parent” field when creating a new record in a One2Many

That is correct, but that happens after u click the save button to persist the new input from the popup. But the requirement is not like that. The requirement wants to show some values from the Parent in the pop-up (please see the screenshot of the wizard form above), and use that information to give the user an idea of what to input. Such as Project remaining days, etc (in my case)

Below is a screenshot of the pop-up form if initiated from the Plus button

The yellow-circled fields are the data that are supposed to be derived from the Parent object. The requirement is to have all that data appear exactly as it does on the Wizard form.

No but of course the Many2One field must be present in the view.

As I already said, Function field can be updated before saving only if the getter is an on_change_with method.

1 Like

Thank you, after I code:

@fields.depends('project')
def on_change_with_project(self):
   if self.project:
      #--- start filling the required values ---

I get all required values from the parent. Thanks:+1:

1 Like