def add(self, order_id, option_id, access_token=None, **post): try: order_sudo = self._document_check_access('sale.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') option_sudo = request.env['sale.order.option'].sudo().browse(option_id) if order_sudo != option_sudo.order_id: return request.redirect(order_sudo.get_portal_url()) option_sudo.add_option_to_order() return request.redirect(option_sudo.order_id.get_portal_url(anchor='details'))
def survey_retry(self, survey_token, answer_token, **post): """ This route is called whenever the user has attempts left and hits the 'Retry' button after failing the survey.""" access_data = self._get_access_data(survey_token, answer_token, ensure_token=True) if access_data['validity_code'] is not True and access_data[ 'validity_code'] != 'answer_done': return self._redirect_with_error(access_data, access_data['validity_code']) survey_sudo, answer_sudo = access_data['survey_sudo'], access_data[ 'answer_sudo'] if not answer_sudo: # attempts to 'retry' without having tried first return werkzeug.utils.redirect("/") try: retry_answer_sudo = survey_sudo._create_answer( user=request.env.user, partner=answer_sudo.partner_id, email=answer_sudo.email, invite_token=answer_sudo.invite_token, **self._prepare_retry_additional_values(answer_sudo)) except: return werkzeug.utils.redirect("/") return request.redirect( '/survey/start/%s?%s' % (survey_sudo.access_token, keep_query('*', answer_token=retry_answer_sudo.token)))
def registration_confirm(self, event, **post): order = request.website.sale_get_order(force_create=1) attendee_ids = set() registrations = self._process_registration_details(post) for registration in registrations: ticket = request.env['event.event.ticket'].sudo().browse(int(registration['ticket_id'])) cart_values = order.with_context(event_ticket_id=ticket.id, fixed_price=True)._cart_update(product_id=ticket.product_id.id, add_qty=1, registration_data=[registration]) attendee_ids |= set(cart_values.get('attendee_ids', [])) # free tickets -> order with amount = 0: auto-confirm, no checkout if not order.amount_total: order.action_confirm() # tde notsure: email sending ? attendees = request.env['event.registration'].browse(list(attendee_ids)).sudo() # clean context and session, then redirect to the confirmation page request.website.sale_reset() urls = event._get_event_resource_urls() return request.render("website_event.registration_complete", { 'attendees': attendees, 'event': event, 'google_url': urls.get('google_url'), 'iCal_url': urls.get('iCal_url') }) return request.redirect("/shop/checkout")
def portal_my_invoice_detail(self, invoice_id, access_token=None, report_type=None, download=False, **kw): try: invoice_sudo = self._document_check_access('account.move', invoice_id, access_token) except (AccessError, MissingError): return request.redirect('/my') if report_type in ('html', 'pdf', 'text'): return self._show_report(model=invoice_sudo, report_type=report_type, report_ref='account.account_invoices', download=download) values = self._invoice_get_page_view_values(invoice_sudo, access_token, **kw) acquirers = values.get('acquirers') if acquirers: country_id = values.get('partner_id') and values.get( 'partner_id')[0].country_id.id values['acq_extra_fees'] = acquirers.get_acquirer_extra_fees( invoice_sudo.amount_residual, invoice_sudo.currency_id, country_id) return request.render("account.portal_invoice_page", values)
def portal_my_task(self, task_id, access_token=None, **kw): try: task_sudo = self._document_check_access('project.task', task_id, access_token) except (AccessError, MissingError): return request.redirect('/my') values = self._task_get_page_view_values(task_sudo, access_token, **kw) return request.render("project.portal_my_task", values)
def portal_my_purchase_order(self, order_id=None, access_token=None, **kw): try: order_sudo = self._document_check_access('purchase.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') values = self._purchase_order_get_page_view_values( order_sudo, access_token, **kw) return request.render("purchase.portal_my_purchase_order", values)
def portal_my_project(self, project_id=None, access_token=None, **kw): try: project_sudo = self._document_check_access('project.project', project_id, access_token) except (AccessError, MissingError): return request.redirect('/my') values = self._project_get_page_view_values(project_sudo, access_token, **kw) return request.render("project.portal_my_project", values)
def event(self, event, **post): if not event.can_access_from_current_website(): raise werkzeug.exceptions.NotFound() if event.menu_id and event.menu_id.child_id: target_url = event.menu_id.child_id[0].url else: target_url = '/event/%s/register' % str(event.id) if post.get('enable_editor') == '1': target_url += '?enable_editor=1' return request.redirect(target_url)
def decline(self, order_id, access_token=None, **post): try: order_sudo = self._document_check_access('sale.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') message = post.get('decline_message') query_string = False if order_sudo.has_to_be_signed() and message: order_sudo.action_cancel() _message_post_helper( 'sale.order', order_id, message, **{'token': access_token} if access_token else {}) else: query_string = "&message=cant_reject" return request.redirect( order_sudo.get_portal_url(query_string=query_string))
def invoice_pay_token(self, invoice_id, pm_id=None, **kwargs): """ Use a token to perform a s2s transaction """ error_url = kwargs.get('error_url', '/my') access_token = kwargs.get('access_token') params = {} if access_token: params['access_token'] = access_token invoice_sudo = request.env['account.move'].sudo().browse( invoice_id).exists() if not invoice_sudo: params['error'] = 'pay_invoice_invalid_doc' return request.redirect(_build_url_w_params(error_url, params)) success_url = kwargs.get( 'success_url', "%s?%s" % (invoice_sudo.access_url, url_encode( {'access_token': access_token}) if access_token else '')) try: token = request.env['payment.token'].sudo().browse(int(pm_id)) except (ValueError, TypeError): token = False token_owner = invoice_sudo.partner_id if request.env.user._is_public( ) else request.env.user.partner_id if not token or token.partner_id != token_owner: params['error'] = 'pay_invoice_invalid_token' return request.redirect(_build_url_w_params(error_url, params)) vals = { 'payment_token_id': token.id, 'type': 'server2server', 'return_url': _build_url_w_params(success_url, params), } tx = invoice_sudo._create_payment_transaction(vals) PaymentProcessing.add_payment_transaction(tx) params['success'] = 'pay_invoice' return request.redirect('/payment/process')
def survey_test(self, survey_token, **kwargs): """ Test mode for surveys: create a test answer, only for managers or officers testing their surveys """ survey_sudo, dummy = self._fetch_from_access_token(survey_token, False) try: answer_sudo = survey_sudo._create_answer(user=request.env.user, test_entry=True) except: return werkzeug.utils.redirect('/') return request.redirect( '/survey/start/%s?%s' % (survey_sudo.access_token, keep_query('*', answer_token=answer_sudo.token)))
def mailing(self, mailing_id, email=None, res_id=None, token="", **post): mailing = request.env['mailing.mailing'].sudo().browse(mailing_id) if mailing.exists(): res_id = res_id and int(res_id) if not self._valid_unsubscribe_token(mailing_id, res_id, email, str(token)): raise exceptions.AccessDenied() if mailing.mailing_model_real == 'mailing.contact': # Unsubscribe directly + Let the user choose his subscriptions mailing.update_opt_out(email, mailing.contact_list_ids.ids, True) contacts = request.env['mailing.contact'].sudo().search([('email_normalized', '=', tools.email_normalize(email))]) subscription_list_ids = contacts.mapped('subscription_list_ids') # In many user are found : if user is opt_out on the list with contact_id 1 but not with contact_id 2, # assume that the user is not opt_out on both # TODO DBE Fixme : Optimise the following to get real opt_out and opt_in opt_out_list_ids = subscription_list_ids.filtered(lambda rel: rel.opt_out).mapped('list_id') opt_in_list_ids = subscription_list_ids.filtered(lambda rel: not rel.opt_out).mapped('list_id') opt_out_list_ids = set([list.id for list in opt_out_list_ids if list not in opt_in_list_ids]) unique_list_ids = set([list.list_id.id for list in subscription_list_ids]) list_ids = request.env['mailing.list'].sudo().browse(unique_list_ids) unsubscribed_list = ', '.join(str(list.name) for list in mailing.contact_list_ids if list.is_public) return request.render('mass_mailing.page_unsubscribe', { 'contacts': contacts, 'list_ids': list_ids, 'opt_out_list_ids': opt_out_list_ids, 'unsubscribed_list': unsubscribed_list, 'email': email, 'mailing_id': mailing_id, 'res_id': res_id, 'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param('mass_mailing.show_blacklist_buttons'), }) else: opt_in_lists = request.env['mailing.contact.subscription'].sudo().search([ ('contact_id.email_normalized', '=', email), ('opt_out', '=', False) ]).mapped('list_id') blacklist_rec = request.env['mail.blacklist'].sudo()._add(email) self._log_blacklist_action( blacklist_rec, mailing_id, _("""Requested blacklisting via unsubscribe link.""")) return request.render('mass_mailing.page_unsubscribed', { 'email': email, 'mailing_id': mailing_id, 'res_id': res_id, 'list_ids': opt_in_lists, 'show_blacklist_button': request.env['ir.config_parameter'].sudo().get_param( 'mass_mailing.show_blacklist_buttons'), }) return request.redirect('/web')
def portal_my_picking_report(self, picking_id, access_token=None, **kw): """ Print delivery slip for customer, using either access rights or access token to be sure customer has access """ try: picking_sudo = self._stock_picking_check_access(picking_id, access_token=access_token) except exceptions.AccessError: return request.redirect('/my') # print report as sudo, since it require access to product, taxes, payment term etc.. and portal does not have those access rights. pdf = request.env.ref('stock.action_report_delivery').sudo().render_qweb_pdf([picking_sudo.id])[0] pdfhttpheaders = [ ('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] return request.make_response(pdf, headers=pdfhttpheaders)
def payment_token(self, order_id, pm_id=None, **kwargs): order = request.env['sale.order'].sudo().browse(order_id) if not order: return request.redirect("/my/orders") if not order.order_line or pm_id is None or not order.has_to_be_paid(): return request.redirect(order.get_portal_url()) # try to convert pm_id into an integer, if it doesn't work redirect the user to the quote try: pm_id = int(pm_id) except ValueError: return request.redirect(order.get_portal_url()) # Create transaction vals = { 'payment_token_id': pm_id, 'type': 'server2server', 'return_url': order.get_portal_url(), } tx = order._create_payment_transaction(vals) PaymentProcessing.add_payment_transaction(tx) return request.redirect('/payment/process')
def survey_start(self, survey_token, answer_token=None, email=False, **post): """ Start a survey by providing * a token linked to a survey; * a token linked to an answer or generate a new token if access is allowed; """ access_data = self._get_access_data(survey_token, answer_token, ensure_token=False) if access_data['validity_code'] is not True: return self._redirect_with_error(access_data, access_data['validity_code']) survey_sudo, answer_sudo = access_data['survey_sudo'], access_data[ 'answer_sudo'] if not answer_sudo: try: answer_sudo = survey_sudo._create_answer(user=request.env.user, email=email) except UserError: answer_sudo = False if not answer_sudo: try: survey_sudo.with_user( request.env.user).check_access_rights('read') survey_sudo.with_user( request.env.user).check_access_rule('read') except: return werkzeug.utils.redirect("/") else: return request.render("survey.403", {'survey': survey_sudo}) # Select the right page if answer_sudo.state == 'new': # Intro page data = {'survey': survey_sudo, 'answer': answer_sudo, 'page': 0} return request.render('survey.survey_init', data) else: return request.redirect( '/survey/fill/%s/%s' % (survey_sudo.access_token, answer_sudo.token))
def update_line_dict(self, line_id, remove=False, unlink=False, order_id=None, access_token=None, input_quantity=False, **kwargs): try: order_sudo = self._document_check_access('sale.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') if order_sudo.state not in ('draft', 'sent'): return False order_line = request.env['sale.order.line'].sudo().browse(int(line_id)) if order_line.order_id != order_sudo: return False if unlink: order_line.unlink() return False # return False to reload the page, the line must move back to options and the JS doesn't handle it if input_quantity is not False: quantity = input_quantity else: number = -1 if remove else 1 quantity = order_line.product_uom_qty + number if quantity < 0: quantity = 0.0 order_line.write({'product_uom_qty': quantity}) currency = order_sudo.currency_id format_price = partial(formatLang, request.env, digits=currency.decimal_places) results = { 'order_line_product_uom_qty': str(quantity), 'order_line_price_total': format_price(order_line.price_total), 'order_line_price_subtotal': format_price(order_line.price_subtotal), 'order_amount_total': format_price(order_sudo.amount_total), 'order_amount_untaxed': format_price(order_sudo.amount_untaxed), 'order_amount_tax': format_price(order_sudo.amount_tax), 'order_amount_undiscounted': format_price(order_sudo.amount_undiscounted), } try: results['order_totals_table'] = request.env['ir.ui.view'].render_template('sale.sale_order_portal_content_totals_table', {'sale_order': order_sudo}) except ValueError: pass return results
def portal_order_page(self, order_id, report_type=None, access_token=None, message=False, download=False, **kw): try: order_sudo = self._document_check_access('sale.order', order_id, access_token=access_token) except (AccessError, MissingError): return request.redirect('/my') if report_type in ('html', 'pdf', 'text'): return self._show_report(model=order_sudo, report_type=report_type, report_ref='sale.action_report_saleorder', download=download) # use sudo to allow accessing/viewing orders for public user # only if he knows the private token now = fields.Date.today() # Log only once a day if order_sudo and request.session.get( 'view_quote_%s' % order_sudo.id ) != now and request.env.user.share and access_token: request.session['view_quote_%s' % order_sudo.id] = now body = _( 'Quotation viewed by customer %s') % order_sudo.partner_id.name _message_post_helper('sale.order', order_sudo.id, body, token=order_sudo.access_token, message_type='notification', subtype="mail.mt_note") values = { 'sale_order': order_sudo, 'message': message, 'token': access_token, 'return_url': '/shop/payment/validate', 'bootstrap_formatting': True, 'partner_id': order_sudo.partner_id.id, 'report_type': 'html', 'action': order_sudo._get_portal_return_action(), } if order_sudo.company_id: values['res_company'] = order_sudo.company_id if order_sudo.has_to_be_paid(): domain = expression.AND( [[ '&', ('state', 'in', ['enabled', 'test']), ('company_id', '=', order_sudo.company_id.id) ], [ '|', ('country_ids', '=', False), ('country_ids', 'in', [order_sudo.partner_id.country_id.id]) ]]) acquirers = request.env['payment.acquirer'].sudo().search(domain) values['acquirers'] = acquirers.filtered(lambda acq: ( acq.payment_flow == 'form' and acq.view_template_id) or ( acq.payment_flow == 's2s' and acq. registration_view_template_id)) values['pms'] = request.env['payment.token'].search([ ('partner_id', '=', order_sudo.partner_id.id) ]) values['acq_extra_fees'] = acquirers.get_acquirer_extra_fees( order_sudo.amount_total, order_sudo.currency_id, order_sudo.partner_id.country_id.id) if order_sudo.state in ('draft', 'sent', 'cancel'): history = request.session.get('my_quotations_history', []) else: history = request.session.get('my_orders_history', []) values.update(get_records_pager(history, order_sudo)) return request.render('sale.sale_order_portal_template', values)
def _prepare_blog_values(self, blogs, blog=False, date_begin=False, date_end=False, tags=False, state=False, page=False): """ Prepare all values to display the blogs index page or one specific blog""" BlogPost = request.env['blog.post'] # prepare domain domain = request.website.website_domain() if blog: domain += [('blog_id', '=', blog.id)] if date_begin and date_end: domain += [("post_date", ">=", date_begin), ("post_date", "<=", date_end)] active_tag_ids = tags and [unslug(tag)[1] for tag in tags.split(',')] or [] if active_tag_ids: fixed_tag_slug = ",".join(slug(t) for t in request.env['blog.tag'].browse(active_tag_ids)) if fixed_tag_slug != tags: return request.redirect(request.httprequest.full_path.replace("/tag/%s/" % tags, "/tag/%s/" % fixed_tag_slug, 1), 301) domain += [('tag_ids', 'in', active_tag_ids)] if request.env.user.has_group('website.group_website_designer'): count_domain = domain + [("website_published", "=", True), ("post_date", "<=", fields.Datetime.now())] published_count = BlogPost.search_count(count_domain) unpublished_count = BlogPost.search_count(domain) - published_count if state == "published": domain += [("website_published", "=", True), ("post_date", "<=", fields.Datetime.now())] elif state == "unpublished": domain += ['|', ("website_published", "=", False), ("post_date", ">", fields.Datetime.now())] else: domain += [("post_date", "<=", fields.Datetime.now())] use_cover = request.website.viewref('website_blog.opt_blog_cover_post').active fullwidth_cover = request.website.viewref('website_blog.opt_blog_cover_post_fullwidth_design').active # if blog, we show blog title, if use_cover and not fullwidth_cover we need pager + latest always offset = (page - 1) * self._blog_post_per_page first_post = BlogPost if not blog: first_post = BlogPost.search(domain + [('website_published', '=', True)], order="post_date desc, id asc", limit=1) if use_cover and not fullwidth_cover: offset += 1 posts = BlogPost.search(domain, offset=offset, limit=self._blog_post_per_page, order="is_published desc, post_date desc, id asc") total = BlogPost.search_count(domain) pager = request.website.pager( url=request.httprequest.path.partition('/page/')[0], total=total, page=page, step=self._blog_post_per_page, ) all_tags = blog and blogs.all_tags()[blog.id] or blogs.all_tags(join=True) tag_category = sorted(all_tags.mapped('category_id'), key=lambda category: category.name.upper()) other_tags = sorted(all_tags.filtered(lambda x: not x.category_id), key=lambda tag: tag.name.upper()) # for performance prefetch the first post with the others post_ids = (first_post | posts).ids return { 'date_begin': date_begin, 'date_end': date_end, 'first_post': first_post.with_prefetch(post_ids), 'other_tags': other_tags, 'tag_category': tag_category, 'nav_list': self.nav_list(), 'tags_list': self.tags_list, 'pager': pager, 'posts': posts.with_prefetch(post_ids), 'tag': tags, 'active_tag_ids': active_tag_ids, 'domain': domain, 'state_info': state and {"state": state, "published": published_count, "unpublished": unpublished_count}, 'blogs': blogs, 'blog': blog, }
def blog_post(self, blog, blog_post, tag_id=None, page=1, enable_editor=None, **post): """ Prepare all values to display the blog. :return dict values: values for the templates, containing - 'blog_post': browse of the current post - 'blog': browse of the current blog - 'blogs': list of browse records of blogs - 'tag': current tag, if tag_id in parameters - 'tags': all tags, for tag-based navigation - 'pager': a pager on the comments - 'nav_list': a dict [year][month] for archives navigation - 'next_post': next blog post, to direct the user towards the next interesting post """ if not blog.can_access_from_current_website(): raise werkzeug.exceptions.NotFound() BlogPost = request.env['blog.post'] date_begin, date_end = post.get('date_begin'), post.get('date_end') pager_url = "/blogpost/%s" % blog_post.id pager = request.website.pager( url=pager_url, total=len(blog_post.website_message_ids), page=page, step=self._post_comment_per_page, scope=7 ) pager_begin = (page - 1) * self._post_comment_per_page pager_end = page * self._post_comment_per_page comments = blog_post.website_message_ids[pager_begin:pager_end] domain = request.website.website_domain() blogs = blog.search(domain, order="create_date, id asc") tag = None if tag_id: tag = request.env['blog.tag'].browse(int(tag_id)) blog_url = QueryURL('', ['blog', 'tag'], blog=blog_post.blog_id, tag=tag, date_begin=date_begin, date_end=date_end) if not blog_post.blog_id.id == blog.id: return request.redirect("/blog/%s/post/%s" % (slug(blog_post.blog_id), slug(blog_post)), code=301) tags = request.env['blog.tag'].search([]) # Find next Post blog_post_domain = [('blog_id', '=', blog.id)] if not request.env.user.has_group('website.group_website_designer'): blog_post_domain += [('post_date', '<=', fields.Datetime.now())] all_post = BlogPost.search(blog_post_domain) if blog_post not in all_post: return request.redirect("/blog/%s" % (slug(blog_post.blog_id))) # should always return at least the current post all_post_ids = all_post.ids current_blog_post_index = all_post_ids.index(blog_post.id) nb_posts = len(all_post_ids) next_post_id = all_post_ids[(current_blog_post_index + 1) % nb_posts] if nb_posts > 1 else None next_post = next_post_id and BlogPost.browse(next_post_id) or False values = { 'tags': tags, 'tag': tag, 'blog': blog, 'blog_post': blog_post, 'blogs': blogs, 'main_object': blog_post, 'nav_list': self.nav_list(blog), 'enable_editor': enable_editor, 'next_post': next_post, 'date': date_begin, 'blog_url': blog_url, 'pager': pager, 'comments': comments, } response = request.render("website_blog.blog_post_complete", values) request.session[request.session.sid] = request.session.get(request.session.sid, []) if not (blog_post.id in request.session[request.session.sid]): request.session[request.session.sid].append(blog_post.id) # Increase counter blog_post.sudo().write({ 'visits': blog_post.visits + 1, }) return response
def _dispatch(cls): """ Before executing the endpoint method, add website params on request, such as - current website (record) - multilang support (set on cookies) - geoip dict data are added in the session Then follow the parent dispatching. Reminder : Do not use `request.env` before authentication phase, otherwise the env set on request will be created with uid=None (and it is a lazy property) """ request.routing_iteration = getattr(request, 'routing_iteration', 0) + 1 func = None routing_error = None # handle // in url if request.httprequest.method == 'GET' and '//' in request.httprequest.path: new_url = request.httprequest.path.replace( '//', '/') + '?' + request.httprequest.query_string.decode('utf-8') return werkzeug.utils.redirect(new_url, 301) # locate the controller method try: rule, arguments = cls._match(request.httprequest.path) func = rule.endpoint request.is_frontend = func.routing.get('website', False) except werkzeug.exceptions.NotFound as e: # either we have a language prefixed route, either a real 404 # in all cases, website processes them exept if second element is static # Checking static will avoid to generate an expensive 404 web page since # most of the time the browser is loading and inexisting assets or image. A standard 404 is enough. # Earlier check would be difficult since we don't want to break data modules path_components = request.httprequest.path.split('/') request.is_frontend = len(path_components) < 3 or path_components[ 2] != 'static' or not '.' in path_components[-1] routing_error = e request.is_frontend_multilang = not func or ( func and request.is_frontend and func.routing.get('multilang', func.routing['type'] == 'http')) # check authentication level try: if func: cls._authenticate(func.routing['auth']) elif request.uid is None and request.is_frontend: cls._auth_method_public() except Exception as e: return cls._handle_exception(e) cls._geoip_setup_resolver() cls._geoip_resolve() # For website routes (only), add website params on `request` if request.is_frontend: request.redirect = lambda url, code=302: werkzeug.utils.redirect( url_for(url), code) cls._add_dispatch_parameters(func) path = request.httprequest.path.split('/') default_lg_id = cls._get_default_lang() if request.routing_iteration == 1: is_a_bot = cls.is_a_bot() nearest_lang = not func and cls.get_nearest_lang( request.env['res.lang']._lang_get_code(path[1])) url_lg = nearest_lang and path[1] # The default lang should never be in the URL, and a wrong lang # should never be in the URL. wrong_url_lg = url_lg and (url_lg != request.lang.url_code or url_lg == default_lg_id.url_code) # The lang is missing from the URL if multi lang is enabled for # the route and the current lang is not the default lang. # POST requests are excluded from this condition. missing_url_lg = not url_lg and request.is_frontend_multilang and request.lang != default_lg_id and request.httprequest.method != 'POST' # Bots should never be redirected when the lang is missing # because it is the only way for them to index the default lang. if wrong_url_lg or (missing_url_lg and not is_a_bot): if url_lg: path.pop(1) if request.lang != default_lg_id: path.insert(1, request.lang.url_code) path = '/'.join(path) or '/' routing_error = None redirect = request.redirect( path + '?' + request.httprequest.query_string.decode('utf-8')) redirect.set_cookie('frontend_lang', request.lang.code) return redirect elif url_lg: request.uid = None path.pop(1) routing_error = None return cls.reroute('/'.join(path) or '/') elif missing_url_lg and is_a_bot: # Ensure that if the URL without lang is not redirected, the # current lang is indeed the default lang, because it is the # lang that bots should index in that case. request.lang = default_lg_id request.context = dict(request.context, lang=default_lg_id.code) if request.lang == default_lg_id: context = dict(request.context) context['edit_translations'] = False request.context = context if routing_error: return cls._handle_exception(routing_error) # removed cache for auth public result = super(IrHttp, cls)._dispatch() cook_lang = request.httprequest.cookies.get('frontend_lang') if request.is_frontend and cook_lang != request.lang.code and hasattr( result, 'set_cookie'): result.set_cookie('frontend_lang', request.lang.code) return result