Comments (4)
Do you think the new marshmallow's pre/post processors integration (see #60 (comment)) could be used as a workaround for this ?
from umongo.
Not sure. The on_[g|s]et
callbacks could be executed after an attribute is set.
class User(Document):
birthday = DateTimeField(on_set=self._compute_age) # either here
age = IntField()
def _compute_age(self):
self.age = (datetime.utcnow() - self.birthday).days / 365 # Who cares about precision?
chuck = User()
chuck.age = None
chuck.birthday = datetime.datetime(year=1940, month=3, day=10)
chuck.age = 76
I don't think you can do this with post_load
, can you? AFAIU, post_load
is schema-level, not field-level, it is only called when loading the whole schema (maybe with partial), but not when setting an attribute.
from umongo.
You're right, marshmallow's pre/post processors is not the silver bullet we were waiting for !
I'm thinking of a new way to implement this feature:
on_set
should be simple by adding a check inDataproxy.load
,Dataproxy.set
andDataproxy.set_by_mongo_name
on_get
can be implemented by storing the field data in dataproxy as a lazy object that need evaluation
example:
>>> def capitalize(value):
... print('capitalize !')
... return value.to_upper()
...
>>> def double(value):
... print('double !')
... return value + ' ' + value
...
>>> class User(Document):
... name = fields.StrField(on_get=[capitalize, double])
... lastname = fields.StrField(on_set=[capitalize, double])
...
>>> user = User(name='john', lastname='doe')
capitalize !
double !
>>> user.lastname
'DOE DOE'
>>> user.name
capitalize !
double !
'JOHN JOHN'
>>> lazy_obj = user._data._data['name']
>>> lazy_obj
<LazyObj(fn=double, value=LazyObj(fn=capitalize, value='john'))>
>>> lazy_obj.eval()
capitalize !
double !
'JOHN JOHN'
But I'm still unsure how useful it would be for on_get
... do you see a usecase for this ?
I can think of a way to automatically unserialize data (for example returning a dict
when having a string of json in database). However this feels error-prone (in my example you may want to modified dict
but this will change nothing within the database...)
Usecase for on_set
is pretty obvious (hashing&salting password as you proposed) though.
from umongo.
But I'm still unsure how useful it would be for on_get... do you see a usecase for this ?
I also see more use for on_set
. I guess on_get
came naturally for symmetry reasons. In practice, it could be useful for a field that depends on a lot of other fields with a simple computation. So rather than modifying the field each time one of those other fields is modified, it could be modified on the fly when accessed. This could be better in terms of both performance and code simplicity. But it doesn't have to be done in the same move anyway, it is independent from on_set
.
on_set should be simple by adding a check in Dataproxy.load, Dataproxy.set and Dataproxy.set_by_mongo_name
And Dataproxy.update
, Dataproxy.delete
. I'm not sure about Dataproxy.from_mongo
and Dataproxy._add_missing_fields
.
Questions:
- Should the callbacks be called when loading from Mongo or only when setting values from object world?
- Should there be a mechanism to avoid calling several times the same callback in a load / update operation, but rather do all updates first then call all needed callbacks only once? Tempting, but maybe not that easy, and potentially problematic. The callbacks are not necessarily idempotent like in my age computation example. If the callback counts or adds/appends stuff, the designer might want to have them executed systematically.
- From an implementation perspective, rather than modifying all the methods cited above, maybe there is an alternative where
Dataproxy._data
would be a special kind ofdict
with an overriden__setitem__
. Just a tought. I didn't check feasibility.
from umongo.
Related Issues (20)
- How to reduce time when query doc from mongo with motor driver
- keyPattern not existing in DuplicteKeyError, causing `KeyError` HOT 3
- `find` with `GenericReferenceField` does not return the document.
- pymongo Database class explicitly denies bool HOT 3
- always $set usage with updating from commit
- Date serialization removes microseconds, but not during commit(), only when deserializing from mongo HOT 5
- 'id' based query other than of type ObjectId is returning None HOT 1
- Why does field.UUIDField return the same value for each instance? HOT 4
- Embedded document: unknown "fieldname" field in DB HOT 1
- DictFields and EmbeddedFields aren't created with default values HOT 4
- How to use UUID as _id HOT 3
- How do the isolation test
- Insert many documents at once
- ConstantField produces error when converting to marshmallow schema
- DictField with an EmbeddedDocument value produces error
- Referencing GridFS data?
- [RFC] Drop txmongo support? HOT 2
- Warning: The 'missing' attribute of fields is deprecated HOT 1
- Passing marshmallow Schema options to the models HOT 2
- Add commit_many() function to perform builk updates HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from umongo.