diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ca1d84..089ba81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ Unreleased - Added attribute `server_version` to Database class (M1hacka) - Changed `Engine.create_table_sql()`, `Engine.drop_table_sql()`, `Model.create_table_sql()`, `Model.drop_table_sql()` parameter to db from db_name (M1hacka) - Fix parsing of datetime column type when it includes a timezone (M1hacka) +- Rename `Model.system` to `Model._system` to prevent collision with a column that has the same name +- Rename `Model.readonly` to `Model._readonly` to prevent collision with a column that has the same name +- The `field_names` argument to `Model.to_tsv` is now mandatory +- Improve creation time of model instances by keeping a dictionary of default values v0.9.8 ------ diff --git a/src/infi/clickhouse_orm/models.py b/src/infi/clickhouse_orm/models.py index c2ab40d..d292462 100644 --- a/src/infi/clickhouse_orm/models.py +++ b/src/infi/clickhouse_orm/models.py @@ -34,10 +34,14 @@ class ModelBase(type): fields.update({n: f for n, f in iteritems(attrs) if isinstance(f, Field)}) fields = sorted(iteritems(fields), key=lambda item: item[1].creation_counter) + # Build a dictionary of default values + defaults = {n: f.to_python(f.default, pytz.UTC) for n, f in fields} + attrs = dict( attrs, _fields=OrderedDict(fields), _writable_fields=OrderedDict([f for f in fields if not f[1].readonly]), + _defaults=defaults ) return super(ModelBase, cls).__new__(cls, str(name), bases, attrs) @@ -116,9 +120,8 @@ class Model(with_metaclass(ModelBase)): Unrecognized field names will cause an `AttributeError`. ''' super(Model, self).__init__() - - self._database = None - + # Assign default values + self.__dict__.update(self._defaults) # Assign field values from keyword arguments for name, value in iteritems(kwargs): field = self.get_field(name) @@ -126,10 +129,6 @@ class Model(with_metaclass(ModelBase)): setattr(self, name, value) else: raise AttributeError('%s does not have a field called %s' % (self.__class__.__name__, name)) - # Assign default values for fields not included in the keyword arguments - for name, field in iteritems(self.fields()): - if name not in kwargs: - setattr(self, name, field.default) def __setattr__(self, name, value): ''' @@ -168,8 +167,7 @@ class Model(with_metaclass(ModelBase)): ''' Gets a `Field` instance given its name, or `None` if not found. ''' - field = getattr(self.__class__, name, None) - return field if isinstance(field, Field) else None + return self._fields.get(name) @classmethod def table_name(cls):