[FIX] website: delete cow view on module update
Before this commit, when a view was removed during a module update (eg: the record was deleted from the file), its COW views would not be deleted. This could lead to unwanted behaviors including tracebacks(1). This commit is somehow related/an extension ofb5fe23055dthat handle COW view write during module update and2e32cc5aa3that remove COW views during module uninstall. task-1931683 Note: Some existing tests had to be run post install (1) A view doing a t-call is COW'd, then that view and its t-called view are removed. If the cow view is not removed, the t-call will crash (see tests in this commit for detailed case). closes odoo/odoo#31295 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- RECORDS FOR RESET VIEWS TESTS -->
|
||||
<record id="test_view" model="ir.ui.view">
|
||||
<field name="name">Test View</field>
|
||||
<field name="type">qweb</field>
|
||||
@@ -50,5 +52,11 @@
|
||||
<p>placeholder</p>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- RECORDS FOR MODULE OPERATION TESTS -->
|
||||
<template id="update_module_base_view">
|
||||
<div>I am a base view</div>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_reset_views
|
||||
from . import test_views_during_module_operation
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import TransactionCase, tagged
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestViewsDuringModuleOperation(TransactionCase):
|
||||
def test_01_cow_views_unlink_on_module_update(self):
|
||||
""" Ensure COW views are correctly removed during module update.
|
||||
Not removing the view could lead to traceback:
|
||||
- Having a view A
|
||||
- Having a view B that inherits from a view C
|
||||
- View B t-call view A
|
||||
- COW view B
|
||||
- Delete view A and B from module datas and update it
|
||||
- Rendering view C will crash since it will render child view B that
|
||||
t-call unexisting view A
|
||||
"""
|
||||
|
||||
View = self.env['ir.ui.view']
|
||||
Imd = self.env['ir.model.data']
|
||||
|
||||
update_module_base_view = self.env.ref('test_website.update_module_base_view')
|
||||
update_module_view_to_be_t_called = View.create({
|
||||
'name': 'View to be t-called',
|
||||
'type': 'qweb',
|
||||
'arch': '<div>I will be t-called</div>',
|
||||
'key': 'test_website.update_module_view_to_be_t_called',
|
||||
})
|
||||
update_module_child_view = View.create({
|
||||
'name': 'Child View',
|
||||
'mode': 'extension',
|
||||
'inherit_id': update_module_base_view.id,
|
||||
'arch': '''
|
||||
<div position="inside">
|
||||
<t t-call="test_website.update_module_view_to_be_t_called"/>
|
||||
</div>
|
||||
''',
|
||||
'key': 'test_website.update_module_child_view',
|
||||
})
|
||||
|
||||
# Create IMD so when updating the module the views will be removed (not found in file)
|
||||
Imd.create({
|
||||
'module': 'test_website',
|
||||
'name': 'update_module_view_to_be_t_called',
|
||||
'model': 'ir.ui.view',
|
||||
'res_id': update_module_view_to_be_t_called.id,
|
||||
})
|
||||
Imd.create({
|
||||
'module': 'test_website',
|
||||
'name': 'update_module_child_view',
|
||||
'model': 'ir.ui.view',
|
||||
'res_id': update_module_child_view.id,
|
||||
})
|
||||
|
||||
# Trigger COW on child view
|
||||
update_module_child_view.with_context(website_id=1).write({'name': 'Child View (W1)'})
|
||||
|
||||
# Ensure views are correctly setup
|
||||
self.assertEquals(View.search_count([('type', '=', 'qweb'), ('key', '=', update_module_child_view.key)]), 2)
|
||||
self.assertTrue(self.env.ref(update_module_view_to_be_t_called.key))
|
||||
self.assertTrue(self.env.ref(update_module_base_view.key))
|
||||
|
||||
# Uninstall module
|
||||
test_website_module = self.env['ir.module.module'].search([('name', '=', 'test_website')])
|
||||
test_website_module.button_immediate_upgrade()
|
||||
|
||||
# Ensure generic views got removed
|
||||
self.assertFalse(self.env.ref('test_website.update_module_view_to_be_t_called', raise_if_not_found=False))
|
||||
# Ensure specific COW views got removed
|
||||
self.assertEquals(View.search_count([('type', '=', 'qweb'), ('key', '=', 'test_website.update_module_child_view')]), 0)
|
||||
@@ -158,6 +158,9 @@ class View(models.Model):
|
||||
# care of creating pages and menus.
|
||||
view.with_context(website_id=website.id).write({'name': view.name})
|
||||
|
||||
if self.pool._init:
|
||||
self += self._get_specific_views()
|
||||
|
||||
result = super(View, self).unlink()
|
||||
self.clear_caches()
|
||||
return result
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# coding: utf-8
|
||||
from odoo.tests import common, HttpCase
|
||||
from odoo.tests import common, HttpCase, tagged
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestPage(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestPage, self).setUp()
|
||||
|
||||
@@ -10,7 +10,7 @@ import unittest
|
||||
from lxml import etree as ET, html
|
||||
from lxml.html import builder as h
|
||||
|
||||
from odoo.tests import common, HttpCase
|
||||
from odoo.tests import common, HttpCase, tagged
|
||||
|
||||
|
||||
def attrs(**kwargs):
|
||||
@@ -264,6 +264,7 @@ class TestViewSaving(common.TransactionCase):
|
||||
)
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestCowViewSaving(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestCowViewSaving, self).setUp()
|
||||
|
||||
Reference in New Issue
Block a user