diff --git a/odoo/addons/base/ir/ir_model.py b/odoo/addons/base/ir/ir_model.py
index b57c8de4fd09889bd16a541911b1a560c1c740c8..79d191dce423b93bed4801cf212e9d38eddf74c0 100644
--- a/odoo/addons/base/ir/ir_model.py
+++ b/odoo/addons/base/ir/ir_model.py
@@ -1,6 +1,9 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
+import datetime
+import dateutil
 import logging
+import time
 from collections import defaultdict
 
 from odoo import api, fields, models, SUPERUSER_ID, tools,  _
@@ -18,6 +21,20 @@ def encode(s):
     return s.encode('utf8') if isinstance(s, unicode) else s
 
 
+# base environment for doing a safe_eval
+SAFE_EVAL_BASE = {
+    'datetime': datetime,
+    'dateutil': dateutil,
+    'time': time,
+}
+
+def make_compute(text, deps):
+    """ Return a compute function from its code body and dependencies. """
+    func = lambda self: safe_eval(text, SAFE_EVAL_BASE, {'self': self}, mode="exec")
+    deps = [arg.strip() for arg in (deps or "").split(",")]
+    return api.depends(*deps)(func)
+
+
 #
 # IMPORTANT: this must be the first model declared in the module
 #
@@ -557,6 +574,57 @@ class IrModelFields(models.Model):
             res.append((field.id, '%s (%s)' % (field.field_description, field.model)))
         return res
 
+    @api.model
+    def _instanciate(self, field_data, partial):
+        """ Return a field instance corresponding to parameters ``field_data``. """
+        attrs = {
+            'manual': True,
+            'string': field_data['field_description'],
+            'help': field_data['help'],
+            'index': bool(field_data['index']),
+            'copy': bool(field_data['copy']),
+            'related': field_data['related'],
+            'required': bool(field_data['required']),
+            'readonly': bool(field_data['readonly']),
+            'store': bool(field_data['store']),
+        }
+        # FIXME: ignore field_data['serialization_field_id']
+        if field_data['ttype'] in ('char', 'text', 'html'):
+            attrs['translate'] = bool(field_data['translate'])
+            attrs['size'] = field_data['size'] or None
+        elif field_data['ttype'] in ('selection', 'reference'):
+            attrs['selection'] = safe_eval(field_data['selection'])
+        elif field_data['ttype'] == 'many2one':
+            if partial and field_data['relation'] not in self.env:
+                return
+            attrs['comodel_name'] = field_data['relation']
+            attrs['ondelete'] = field_data['on_delete']
+            attrs['domain'] = safe_eval(field_data['domain']) if field_data['domain'] else None
+        elif field_data['ttype'] == 'one2many':
+            if partial and not (
+                field_data['relation'] in self.env and (
+                    field_data['relation_field'] in self.env[field_data['relation']]._fields or
+                    field_data['relation_field'] in self.pool.get_manual_fields(self._cr, field_data['relation'])
+            )):
+                return
+            attrs['comodel_name'] = field_data['relation']
+            attrs['inverse_name'] = field_data['relation_field']
+            attrs['domain'] = safe_eval(field_data['domain']) if field_data['domain'] else None
+        elif field_data['ttype'] == 'many2many':
+            if partial and field_data['relation'] not in self.env:
+                return
+            attrs['comodel_name'] = field_data['relation']
+            rel, col1, col2 = self._custom_many2many_names(field_data['model'], field_data['relation'])
+            attrs['relation'] = field_data['relation_table'] or rel
+            attrs['column1'] = field_data['column1'] or col1
+            attrs['column2'] = field_data['column2'] or col2
+            attrs['domain'] = safe_eval(field_data['domain']) if field_data['domain'] else None
+        # add compute function if given
+        if field_data['compute']:
+            attrs['compute'] = make_compute(field_data['compute'], field_data['depends'])
+
+        return fields.Field.by_type[field_data['ttype']](**attrs)
+
 
 class IrModelConstraint(models.Model):
     """
diff --git a/odoo/models.py b/odoo/models.py
index dff252d0d3e0a38e1581faee7f9a62fc8b1494f4..12c9becc6ac20f5621704858ff6c827f62ffe938 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -29,7 +29,6 @@ import logging
 import operator
 import pytz
 import re
-import time
 from collections import defaultdict, MutableMapping, OrderedDict
 from inspect import getmembers, currentframe
 from operator import attrgetter, itemgetter
@@ -65,20 +64,6 @@ onchange_v7 = re.compile(r"^(\w+)\((.*)\)$")
 
 AUTOINIT_RECALCULATE_STORED_FIELDS = 1000
 
-# base environment for doing a safe_eval
-SAFE_EVAL_BASE = {
-    'datetime': datetime,
-    'dateutil': dateutil,
-    'time': time,
-}
-
-def make_compute(text, deps):
-    """ Return a compute function from its code body and dependencies. """
-    func = lambda self: safe_eval(text, SAFE_EVAL_BASE, {'self': self}, mode="exec")
-    deps = [arg.strip() for arg in (deps or "").split(",")]
-    return api.depends(*deps)(func)
-
-
 def check_object_name(name):
     """ Check if the given name is a valid model name.
 
@@ -646,57 +631,13 @@ class BaseModel(object):
 
     @api.model
     def _add_manual_fields(self, partial):
+        IrModelFields = self.env['ir.model.fields']
         manual_fields = self.pool.get_manual_fields(self._cr, self._name)
-
-        for name, field in manual_fields.iteritems():
-            if name in self._fields:
-                continue
-            attrs = {
-                'manual': True,
-                'string': field['field_description'],
-                'help': field['help'],
-                'index': bool(field['index']),
-                'copy': bool(field['copy']),
-                'related': field['related'],
-                'required': bool(field['required']),
-                'readonly': bool(field['readonly']),
-                'store': bool(field['store']),
-            }
-            # FIXME: ignore field['serialization_field_id']
-            if field['ttype'] in ('char', 'text', 'html'):
-                attrs['translate'] = bool(field['translate'])
-                attrs['size'] = field['size'] or None
-            elif field['ttype'] in ('selection', 'reference'):
-                attrs['selection'] = safe_eval(field['selection'])
-            elif field['ttype'] == 'many2one':
-                if partial and field['relation'] not in self.env:
-                    continue
-                attrs['comodel_name'] = field['relation']
-                attrs['ondelete'] = field['on_delete']
-                attrs['domain'] = safe_eval(field['domain']) if field['domain'] else None
-            elif field['ttype'] == 'one2many':
-                if partial and not (
-                    field['relation'] in self.env and (
-                        field['relation_field'] in self.env[field['relation']]._fields or
-                        field['relation_field'] in self.pool.get_manual_fields(self._cr, field['relation'])
-                )):
-                    continue
-                attrs['comodel_name'] = field['relation']
-                attrs['inverse_name'] = field['relation_field']
-                attrs['domain'] = safe_eval(field['domain']) if field['domain'] else None
-            elif field['ttype'] == 'many2many':
-                if partial and field['relation'] not in self.env:
-                    continue
-                attrs['comodel_name'] = field['relation']
-                rel, col1, col2 = self.env['ir.model.fields']._custom_many2many_names(field['model'], field['relation'])
-                attrs['relation'] = field['relation_table'] or rel
-                attrs['column1'] = field['column1'] or col1
-                attrs['column2'] = field['column2'] or col2
-                attrs['domain'] = safe_eval(field['domain']) if field['domain'] else None
-            # add compute function if given
-            if field['compute']:
-                attrs['compute'] = make_compute(field['compute'], field['depends'])
-            self._add_field(name, Field.by_type[field['ttype']](**attrs))
+        for name, field_data in manual_fields.iteritems():
+            if name not in self._fields:
+                field = IrModelFields._instanciate(field_data, partial)
+                if field:
+                    self._add_field(name, field)
 
     @classmethod
     def _init_constraints_onchanges(cls):