def __init__(self, *args, **kwargs): """Inits the document with given data and validates the fields (field validation bad idea during init?). If you define ``__init__`` method for your document class, make sure to call this :: class MyDoc(BaseDocument, dot_notation=True): foo = Field(str) bar = Field(int, required=False) def __init__(self, *args, **kwargs): super(MyDoc, self).__init__(*args, **kwargs) # do other stuff """ # if input dict, merge (not updating) into kwargs if args and not isinstance(args[0], dict): raise TypeError('dict or dict subclass argument expected') elif args: for field_name, field_value in args[0].items(): if field_name not in kwargs: kwargs[field_name] = field_value super(BaseDocument, self).__init__() for field_name, field in self.nanomongo.fields.items(): if hasattr(field, 'default_value'): val = field.default_value dict.__setitem__(self, field_name, val() if callable(val) else val) # attach get_<field_name>_field methods for DBRef fields if field.data_type in [DBRef] + DBRef.__subclasses__(): getter_name = 'get_%s_field' % field_name doc_class = field.document_class if hasattr(field, 'document_class') else None getter = ref_getter_maker(field_name, document_class=doc_class) setattr(self, getter_name, six.create_bound_method(getter, self)) for field_name in kwargs: if self.nanomongo.has_field(field_name): self.nanomongo.validate(field_name, kwargs[field_name]) dict.__setitem__(self, field_name, kwargs[field_name]) else: raise ExtraFieldError('Undefined field %s=%s in %s' % (field_name, kwargs[field_name], self.__class__)) for field_name, field_value in self.items(): # transform dict to RecordingDict so we can track diff in embedded docs if isinstance(field_value, dict): dict.__setitem__(self, field_name, RecordingDict(field_value))