This question has been flagged
2 Replies
9835 Views

Hi,

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']

        context.update(active_id=product.id)

        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.

Avatar
Discard

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.

Author Best Answer

Hi Luke,

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

https://www.odoo.com/forum/help-1/question/fixed-what-is-wrong-with-this-code-73380

(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.

Avatar
Discard
Best Answer

@Manuel,

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:

https://github.com/OdooCommunityWidgets/website_multi_image/blob/8.0/views/website_product_image_carousel.xml

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">
    <div>
        <span t-field="i.image" class="img-responsive" t-field-options="{&quot;widget&quot;: &quot;image&quot;, &quot;class&quot;: &quot;img-responsive&quot;}"/>
    
</div>

</t>

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.

Avatar
Discard