@@ -19,3 +19,115 @@ If you want to have a technical name to reference:
1919 _inherit = ["storage.backend", "server.env.techname.mixin"]
2020
2121 [...]
22+
23+ ## Restoring columns on uninstall
24+
25+ When ` server.env.mixin ` is bound to an existing model, the ORM drops the
26+ original stored columns for all env-managed fields. If the binding addon is
27+ later uninstalled, those columns must be recreated so the database remains
28+ usable.
29+
30+ Add an ` uninstall_hook ` to your addon and delegate to
31+ ` restore_env_managed_columns ` :
32+
33+ # your_addon/__init__.py
34+ from . import models
35+
36+ def uninstall_hook(env):
37+ env["server.env.mixin"].restore_env_managed_columns(
38+ "storage.backend",
39+ ["directory_path", "other_field"],
40+ )
41+
42+ # your_addon/__manifest__.py
43+ {
44+ ...
45+ "uninstall_hook": "uninstall_hook",
46+ }
47+
48+ The helper creates any missing columns (idempotent: safe to call multiple
49+ times) and repopulates them with each record's current effective value —
50+ whether that value came from an environment configuration file or from the
51+ stored default field (` x_<field>_env_default ` ).
52+
53+ The hook must run * before* the ORM extensions are removed, which is guaranteed
54+ by Odoo's uninstall sequence (hooks execute before ` Module.module_uninstall() ` ).
55+
56+ ## Migrating when dropping server_environment dependency
57+
58+ When refactoring an existing addon that embeds a ` server.env.mixin ` binding, you
59+ may want to extract the binding into a separate * glue* addon and drop the
60+ ` server_environment ` dependency from the original. This keeps the base addon
61+ lightweight while preserving server-environment features for those who install
62+ the glue addon.
63+
64+ ** Pattern:**
65+
66+ - ** Original addon (v1)** : depends on ` server_environment ` and binds the mixin
67+ directly in model code.
68+ - ** Refactored addon (v2)** : removes ` server_environment ` from dependencies,
69+ removes the mixin binding and the related ORM model inheritance.
70+ - ** New glue addon** (optional, same version): depends on both ` server_environment `
71+ and the original addon v2; re-adds the mixin binding in a separate module file.
72+
73+ ** Migration checklist:**
74+
75+ 1 . In the ** original addon's v2 ` __manifest__.py ` ** :
76+ - Remove ` "server_environment" ` from ` depends ` .
77+ - Remove the model file(s) that contained the mixin binding.
78+ - Update ` depends ` to add the new glue addon * if* the base addon still needs it
79+ (otherwise, make the glue addon optional for users who want env-binding).
80+
81+ 2 . In the ** original addon's v2 model code** :
82+ - Delete or simplify the model class that inherited from ` server.env.mixin ` .
83+ - If the model was only there for the binding, remove it entirely.
84+ - Restore the original field definitions (not as computed fields).
85+
86+ 3 . ** Create a migration script** (if needed) to restore columns * during the addon
87+ upgrade* , before the ORM model extensions are unloaded. Use a ` @post_load `
88+ hook or a dedicated migration script:
89+
90+ # migrations/18.0.1.0.0/post-restore-columns.py
91+ def migrate(cr, version):
92+ # Call the restoration logic while the v1 model is still active
93+ env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
94+ env["server.env.mixin"].restore_env_managed_columns(
95+ "storage.backend",
96+ ["directory_path", "other_field"],
97+ )
98+
99+ 4 . ** Create the glue addon** with the model re-inheritance:
100+
101+ # your_addon_env/__init__.py
102+ from . import models
103+
104+ # your_addon_env/models/__init__.py
105+ from . import storage_backend
106+
107+ # your_addon_env/models/storage_backend.py
108+ class StorageBackend(models.Model):
109+ _name = "storage.backend"
110+ _inherit = ["storage.backend", "server.env.mixin"]
111+
112+ @property
113+ def _server_env_fields(self):
114+ return {"directory_path": {}}
115+
116+ # your_addon_env/__manifest__.py
117+ {
118+ "name": "Storage Backend – Server Environment",
119+ "version": "18.0.1.0.0",
120+ "depends": ["server_environment", "storage_backend"],
121+ "installable": True,
122+ }
123+
124+ ** Key points:**
125+
126+ - Column restoration must happen * during the addon upgrade* (step 3), not as an
127+ uninstall hook, because the original model binding is still active.
128+ - The ` restore_env_managed_columns ` helper is idempotent and safe to call even
129+ if columns already exist.
130+ - Users who do not need server environment features simply do * not* install the
131+ glue addon—the base addon continues to work with plain database columns.
132+ - Users who do need server environment can install both the base addon (v2+) and
133+ the glue addon (same version) to get the binding back.
0 commit comments