Currently odoo eCommerce is already good to start somewhere. But sometimes, client want to change something that are not covered in odoo base. For example, they want to change the style of pagination, they want to change the numbering, or they want to completely changes the style and have an ellipsis with first and last page always shown. In this article, i will share how to achieve that behavior in Odoo15.
As for some styling, we can easily create new css or even directly change the style via Website Editor. But, to populate the pagination data, it’s applied in the backend. So, we need to create a new module to override the default behavior.
Implementation
We can trace the code to find how Odoo implement pagination. As for eCommerce, it’s first called from controller def shop()
in module website_sale
, then if we search the initialization of that method def pager()
, we can see that it’s initialized from portal controller. But, we found that there is a wrapper inside model website
where it directly call the portal, so it’s easier to just override the method pager
in website
model than override them from the controller, because as we see in the controller def shop()
, it’s just call the method def pager()
from model website
.
So now, we can create new module and inherit model website
and override the method pager()
.
Original method from module website
on file website/models/website.py
@api.model
def pager(self, url, total, page=1, step=30, scope=5, url_args=None):
return pager(url, total, page=page, step=step, scope=scope, url_args=url_args)
And now, we can override the method pager()
in our new module
@api.model
def pager(self, url, total, page=1, step=30, scope=5, url_args=None):
res = super(Website, self).pager(url, total, page=page, step=step, scope=scope, url_args=url_args)
return res
In the code above, we override the method pager()
, and call the super method super(Website, self).pager()
to get the original result. Then, we can modify the result as we want.
If you try to check the result of res
variable, you will see that it’s a dictionary with some keys. The most important keys are page_count
, page
, and pages
. page_count
is the total page, page
is the current page, and pages
is the list of page number that will be shown in the pagination.
Since we’re going to change how pagination number will be shown, we just need to replace the pages
key, but still need the total page and current page to compute where ellipsis should be shown. In the example below, it will show the first and last page, and if there is a gap atleast 3 page between the current page and the first or last page, it will show ellipsis instead of the number.
@api.model
def pager(self, url, total, page=1, step=30, scope=5, url_args=None):
res = super(Website, self).pager(url, total, page=page, step=step, scope=scope, url_args=url_args)
def get_url(page):
_url = "%s/page/%s" % (url, page) if page > 1 else url
if url_args:
_url = "%s?%s" % (_url, urls.url_encode(url_args))
return _url
def get_pager(pcurr, ptotal):
delta = 2 # number of pages to show before and after current page
left = pcurr - delta
right = pcurr + delta + 1
pages = []
pagesWithEllipsis = []
for page in range(1, ptotal+1):
if page == 1 or page == ptotal or (page >= left and page < right):
pages.append(page)
ellips = False
for page in pages:
if ellips:
if page - ellips == 2:
pagesWithEllipsis.append({'url': get_url(ellips + 1), 'num': ellips + 1})
elif page - ellips != 1:
pagesWithEllipsis.append({'url': None, 'num': '...'})
pagesWithEllipsis.append({'url': get_url(page), 'num': page})
ellips = page
return pagesWithEllipsis
res['pages'] = get_pager(res['page']['num'], res['page_count'])
return res
And, here is the result
- First page
- Middle page
- Almost last page
Okay, that’s it. This article is just specific case where client want to change the pagination style, but you can always modify the code to fit your need.
Module: website_pagination