Search code examples
pythonodoo

Odoo 13 : How to write a good filters in order to sent data to odoo website page?



I've been asked to do some filters before passing the data to the website.
I have four(4) models that are linked with many2many fields. Let me add an image of the four models.enter image description here

In order to print the model.a, we need to check if it has model.b linked to it, then check if some model.c is linked to model.b and finally, check if some model.d is linked to model.c. After all of that. The result is the same as this image enter image description here To do that, I wrote this code :

@http.route(['/agenda'], auth="public", website=True)
def agenda(self):
    months = DATES_SELECT
    # all dictionary used in the implementation
    model_c_dict = {}
    model_b_dict = {}
    model_a_dict = {}
    model_a_key = []
    # filter the model.d according to certain condition
    # should I set registrations_left field as store=True for performance when using .search()
    model_d_ids = request.env['model.d'].search([('date_start', '>', dt.now().date()), ('state', '=', 'opened')], order="date_start").filtered(lambda k: k.registrations_left != 0)
    for session in model_d_ids:
        course_id = session.course_id_many[:1]
        if not course_id.state == 'validated':
            continue
        model_c_dict.setdefault(course_id.id, {'object': course_id, 'sessions': []})
        model_c_dict[course_id.id]['sessions'].append(session)
    for k, v in model_c_dict.items():
        category_id = v['object'].category_ids[:1]
        if not category_id:
            continue
        model_b_dict.setdefault(category_id.id, {'object': category_id, 'course': {}})
        model_b_dict[category_id.id]['course'].setdefault(k, v)
    for k, v in model_b_dict.items():
        catalogue_id = v['object'].catalogue_ids[:1]
        if not catalogue_id:
            continue
        model_a_dict.setdefault(catalogue_id.id, {'object': catalogue_id, 'category':  {}})
        model_a_dict[catalogue_id.id]['category'].setdefault(k, v)
        if catalogue_id.id in model_a_dict:
            model_a_key.append(catalogue_id)
    # sort the model_a with model_a.sequence as key
    model_a_key = sorted(list(set(model_a_key)), key=lambda k: k.sequence)

    # pack key
    dict_key = {'model_a_key': model_a_key}

    values = {
        'months': months,
        'categs': model_a_dict,
        'dict_key': dict_key,
    }

    return request.render('website_custom.agenda', values)

It works as intended, but I don't know if It has performance issues, if it's bad coding, ...
So I'm asking your opinion. PS: I didn't design the models and its relations.


Solution

  • I loved the slice technique to avoid index out of range error, and can be very usefull to check if the record is connected all the way up to A (catalogue model) in filtered function k.course_id_many[:1].category_ids[:1].catalogue_ids[:1] but I prefer doing this in the domain:

    @http.route(['/agenda'], auth="public", website=True)
    def agenda(self):
        courses_dict = {}
        category_dict = {}
        catalogue_dict = {}
        # extract all record of Model D connected all the way up to A model
        sessions = request.env['model.d'].search([('date_start', '>', dt.now().date()),
                                                  ('state', '=', 'opened'),
                                                  # this will make sure that the record retrieved will be connected to catalogue model (A)
                                                  ('course_id_many.category_ids.catalogue_ids', '!=', False)], order="date_start") \
            .filtered(lambda k: k.registrations_left != 0)
    
        for session in sessions:
            # if you want to treat olny the first record you can add the slice on the many2many [:1]
            # but I think you will skip the rest of the record in the many2many field
            # and if this what you want the loop are not needed at all just do `course = session.course_id_many[0]`
            # and do the same for all loops. because you don't have to check if the record are connected we all ready did that in search method
            course = session.course_id_many[0]
            if not course.state == 'validated': continue  # skip validated courses
    
            # add course to dict, and add the session to it's list of sessions
            course_obj = courses_dict.setdefault(course.id, {'object': course, 'sessions': []})
            course_obj['sessions'].append(session)
    
            category = course.category_ids[0]
            # store category, and add course to it's list of courses
            category_obj = category_dict.setdefault(category.id, {'object': category, 'course': {}})
            category_obj = category_dict[category.id]['course'][course.id] = course_obj
    
            catalogue = category.catalogue_ids[0]
            # sotre catalog, and add category to it's categories list
            catalogue_dict.setdefault(catalogue.id, {'object': catalogue, 'category': {}})['category'][category.id] = category_obj
    
        # sort catalogue
        catalogue_keys = sorted(catalogue_dict.keys(), key=lambda k: catalogue_dict[k]['object'].sequence)
    
        values = {
            'months': DATES_SELECT,
            'categs': catalogue_dict,
            'dict_key': catalogue_keys,
        }
    
        return request.render('website_custom.agenda', values)
    

    I hope this work I did the best to check for syntax errors, It should work.