Odoo Help


This community is for beginners and experts willing to share their Odoo knowledge. It's not a forum to discuss ideas, but a knowledge base of questions and their answers.


FIXED - Extend website_sale to display product attachments

Manuel Pérez
on 1/11/15, 7:12 AM 2,966 views


I've just started experimenting with Odoo development, and I'm finding it really hard to extend any of the existing website modules. I'd like to develop a module to display product attachments on odoo shop, but I just don't get how. I've replaced the existing product method under the website_sale class with the following code, just to add the attachments to the values dictionary, in order to later display them:

from openerp import SUPERUSER_ID
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website_sale.controllers.main import website_sale

class website_attachments(website_sale):

    @http.route(['/shop/product/<model("product.template"):product>'], type='http', auth="public", website=True)
    def product(self, product, category='', search='', **kwargs):

        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        category_obj = pool['product.public.category']
        template_obj = pool['product.template']


        if category:
            category = category_obj.browse(cr, uid, int(category), context=context)

        attrib_list = request.httprequest.args.getlist('attrib')
        attrib_values = [map(int,v.split("-")) for v in attrib_list if v]
        attrib_set = set([v[1] for v in attrib_values])

        keep = QueryURL('/shop', category=category and category.id, search=search, attrib=attrib_list)

        category_ids = category_obj.search(cr, uid, [], context=context)
        category_list = category_obj.name_get(cr, uid, category_ids, context=context)
        category_list = sorted(category_list, key=lambda category: category[1])

        pricelist = self.get_pricelist()

        from_currency = pool.get('product.price.type')._get_field_currency(cr, uid, 'list_price', context)
        to_currency = pricelist.currency_id
        compute_currency = lambda price: pool['res.currency']._compute(cr, uid, from_currency, to_currency, price, context=context)

        if not context.get('pricelist'):
            context['pricelist'] = int(self.get_pricelist())
            product = template_obj.browse(cr, uid, int(product), context=context)

        attachment_obj = pool['ir.attachment']

        domain=['|',('res_model', '=', 'product.template'), ('res_id', '=', product.id)]
        attachment_ids = attachment_obj.search(cr,uid,domain)
        attachments = attachment_obj.browse(cr, uid, attachment_ids)

        values = {
            'search': search,
            'category': category,
            'pricelist': pricelist,
            'attrib_values': attrib_values,
            'compute_currency': compute_currency,
            'attrib_set': attrib_set,
            'keep': keep,
            'category_list': category_list,
            'main_object': product,
            'product': product,
            'get_attribute_value_ids': self.get_attribute_value_ids,
            'attachments' = attachments
        return request.website.render("website_sale.product", values)

When I try to loop over attachments in the corresponding template (via the online editor), I get the following error:

foreach enumerator 'attachments' is not defined while rendering template 'website_sale.product'


I would appreciate anyone helping on this, I've gone through the technical documentation on the Odoo community and honestly doesn't help much (although it's a good start).

Thanks in advance.

Manuel - this would be a very useful module to have to augment the ecommerce store - it would allow all sorts of technical documents to be made available for immediate download. Slides can do a reasonable job for uploading and rendering pdf files on gDrive but there may be lots of others sorts of file types (spreadsheets, calibration files, cad files, that need to be offered in support of technical products, and this module would provide a simple way to do this.

Kurt Haselwimmer
on 8/26/15, 1:51 PM
Manuel Pérez
On 1/13/15, 4:39 AM

Hi Luke,

I've solved this as detailed in the following question:


(it was a silly mistake at the end)

The reason why I chose attachments instead of binary fields is related to this still unresolved issue with Odoo: https://github.com/odoo/odoo/issues/3792

Thank you so much.


Luke Branch

--Luke Branch--
| 6 7 8
Mui Wo, Lantau, Hong Kong
--Luke Branch--


Luke Branch
On 1/19/15, 9:16 AM


I think this specific issue may be due to your view. Please post back with the view you are trying to use, or a gist to it.

From what I understand of it, for loops require a variable to be defined outside of the loop. There is an example of a t-foreach loop here:


Notice specifically the outside of that the loop is running inside of in bold and the inside of the loop that is to be repeated in italics:

<t t-foreach="product.images" t-as="i">
        <span t-field="i.image" class="img-responsive" t-field-options="{&quot;widget&quot;: &quot;image&quot;, &quot;class&quot;: &quot;img-responsive&quot;}"/>


the key thing you need to notice here is the t-foreach statement (in your case I think it may need to be product.attachments) and the t-as statement (call it t-as="a", or any other string). I believe this variable is used as a sort of counter for the loop to tell it when there are no more items in product.attachments it should stop the loop.

The t-field-options statement is just there to use a widget to display the image, so it may or may not be applicable in your case depending on what you want to display in a list. For me, displaying the items with the image widget was necessary as I did not want the raw binary output in a list.

Try looking through the Odoo source code for their uses of t-foreach and t-as, as I think this is the key to understanding how they should be used.

Your Answer

Please try to give a substantial answer. If you wanted to comment on the question or answer, just use the commenting tool. Please remember that you can always revise your answers - no need to answer the same question twice. Also, please don't forget to vote - it really helps to select the best questions and answers!

About This Community

This community is for professionals and enthusiasts of our products and services. Read Guidelines

Question tools

3 follower(s)


Asked: 1/11/15, 7:12 AM
Seen: 2966 times
Last updated: 8/26/15, 1:51 PM