Question about sort_on a object property

Hi there,

I've this peace of code working well but I need to sort_on de object property "texto", but I cann't access this properties on the portal_catalog.searchResults, anyone can help me please?

 <div class=" "  tal:define="obj_banner python:portal.getObjectById(['configuracao'], 'banner_home');
              caminho python:'/'.join(obj_banner.getPhysicalPath());
                      
                  results python:context.portal_catalog.searchResults(portal_type='Image',
                                                                      sort_on='getObjPositionInParent',
                                                                      sort_order='ascending',
                                                                      path={'query': caminho, 'level': 0,'depth' :1}); ">

                         <tal:listagem tal:repeat="item results">
                                    <tal:Item tal:define="item_url item/getURL|item/absolute_url;
                                      item_id item/getId|item/id;
                                      item_title_or_id item/pretty_title_or_id;
                                      item_obj item/getObject;
                                       item_link python:item_obj.getProperty('link', '');
                                       item_texto python:item_obj.getProperty('texto', '');
                                       ">
                                        <div class="item">
                    <a href="#" tal:attributes="href python:item_link">
                     
               <img src="" tal:attributes="src python:item_url" alt="Slide6" /> 
                     </a>
                    
                </div>                  
                                     </tal:Item>
                                  </tal:listagem > 
   
            
            </div>

Hi,

  • First you need to make sure your texto property is indexed:
    Go to your Plone ZMI, then portal_catalog, then Indexes (url similar to: http://localhost:8080/Plone/portal_catalog/manage_catalogIndexes ).
    If textto is not in the list, it means it is not indexed so you cannot use it in search or sorting.

  • If it is in the list but its index type is ZCTextIndex or KeyworkIndex, then you cannot use for sorting (you probably need a FieldIndex).

To learn about how to declare indexes: http://docs.plone.org/develop/plone/searching_and_indexing/indexing.html

The type of indexer for texto is probably ZCTextIndex which doesn't allow sorting. You can learn more about the differences in:

You can however do the ordering yourself after querying the catalog. I didn't test it but something like:

objs = sorted([brain.getObject() for brain in results], key=lambda obj:obj.texto)

And then you use tal:repeat over objs instead of results.

Hi,

thanks for your reply,

where did I put this "sorted?"

like this?

 <div class=" "  tal:define="obj_banner python:portal.getObjectById(['configuracao'], 'banner_home');
              caminho python:'/'.join(obj_banner.getPhysicalPath());
                      
                  results python:context.portal_catalog.searchResults(portal_type='Image',
                                                                      sort_on='getObjPositionInParent',
                                                                      sort_order='ascending',
                                                                      path={'query': caminho, 'level': 0,'depth' :1}); 
                   objs python:sorted([brain.getObject() for brain in results], key=lambda obj:obj.texto)">

                         <tal:listagem tal:repeat="item objs">
                                    <tal:Item tal:define="item_url item/getURL|item/absolute_url;
                                      item_id item/getId|item/id;
                                      item_title_or_id item/pretty_title_or_id;
                                      item_obj item/getObject;
                                       item_link python:item_obj.getProperty('link', '');
                                       item_texto python:item_obj.getProperty('texto', '');
                                       ">
                                        <div class="item">
                    <a href="#" tal:attributes="href python:item_link">
                     
               <img src="" tal:attributes="src python:item_url" alt="Slide6" /> 
                     </a>
                    
                </div>                  
                                     </tal:Item>
                                  </tal:listagem > 
   
            
            </div>

Yes.

But now you should not call item/getObject anymore because item is already the object. You should replace all item_obj.getProperty(...) with item.getProperty(...).

Ideally you should have it in your browser's view class but yes, it should work where it is (note you can remove getURL and getId references since those are related to brains only). Only item/getObject won't make sense (i.e. will throw an error) since each item will already be the object.

Please test the code and make the needed fixes by reading the links in this thread. Only then you'll understand all you need to do.

Not working :\

Module Products.PageTemplates.ZRPythonExpr, line 48, in call
traceback_info: sorted([brain.getObject() for brain in results], key=lambda obj:obj.texto) Module PythonExpr, line 1, in
NameError: name 'sorted' is not defined

Try:

objs python:[brain.getObject() for brain in results].sort(key=lambda obj:obj.texto)"

If it doesn't work, consider moving your logic to a browser view. There are heaps of documentation in docs.plone.org

hi,

now there is no error but nothing appears..

 <div class=" "  tal:define="obj_banner python:portal.getObjectById(['configuracao'], 'banner_home');
              caminho python:'/'.join(obj_banner.getPhysicalPath());
                      
                  results python:context.portal_catalog.searchResults(portal_type='Image',
                                                                      sort_on='getObjPositionInParent',
                                                                      sort_order='ascending',
                                                                      path={'query': caminho, 'level': 0,'depth' :1}); 
                  objs python:[brain.getObject() for brain in results].sort(key=lambda obj:obj.texto)">

                         <tal:listagem tal:repeat="item objs">
                                    <tal:Item tal:define="item_url item/getURL|item/absolute_url;
                                      item_id item/getId|item/id;
                                      item_title_or_id item/pretty_title_or_id;
                                      item_obj item/getObject;
                                       item_link python:item_obj.getProperty('link', '');
                                       item_texto python:item_obj.getProperty('texto', '');
                                       ">
                                        <div class="item">
                    <a href="#" tal:attributes="href python:item_link">
                     
               <img src="" tal:attributes="src python:item_url" alt="Slide6" /> 
                     </a>
                    
                </div>                  
                                     </tal:Item>
                                  </tal:listagem > 
   
            
            </div>

As I said, untested code :slight_smile: But probably a good pointer so try to move your logic to a browser view and from there you should be able to more easily debug (with pdb) what's wrong.

Alternatively you could try to run pdb from the template itself: https://www.starzel.de/blog/magic-templates-in-plone-5 From there you can inspect why the expression I suggested is returning an empty list.

Again, untested, but I might have realized why nothing appeared. Unlike sorted(), the list.sort method works inplace so nothing was set in the objs variable. You could try:

tal:define="...;
            objs python:[brain.getObject() for brain in results];
            dummy python:objs.sort(key=texto)">

Let us know if it works!

be careful; in Python sorted() and .sort() do not work the same way:

>>> a = [9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> sorted(a)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a
[9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9]

you could end with unexpected results doing that; but maybe in this context is OK to do so.