Comments (4)
The use case presented in the tests above is a bit silly because you can't call __init__
in Document
template anyway.
Also, I should be more explicit about the fact that the point is to get to the parent implementation.
I suppose in some cases, getting the template is enough. The method from the template is unchanged in the implementation. But as soon as the method does stuff in DB, we need the implementation's method. And the implementation from the same instance. Good thing, we do have a link to the instance and the template class so we can do that:
def test_super_in_inheritance(self):
class Parent(Document):
def get_impl_from_tmpl(self, tmpl):
return self.opts.instance.retrieve_document(tmpl)
class Meta:
allow_inheritance = True
name = fields.StrField()
def get_name(self):
return self.name
class Child(Parent):
def get_name(self):
# Option 1 - Works using template's get_name method
name = Parent.get_name(self)
# Option 2 - Works using implementation's get_name method
name = self.get_impl_from_tmpl(Parent).get_name(self)
return name[0]
ParentImpl = self.instance.register(Parent)
ChildImpl = self.instance.register(Child)
child = ChildImpl(name='Toto')
child.get_name()
Rather than using super()
, we can specify the parent explicitly.
Option 1 - The parent class we pass in there will be the template, or the implementation if the document is registered into an implementation with the same name in the namespace (not sure I'm clear, but this is the same mechanism as in above comment).
Option 2 - Or Document
could have an extra method to use the instance (self
) and the parent template to get to the parent implementation in the same instance. The method is get_impl_from_tmpl
. In my test, it is defined in Parent
but in uMongo it would be in Document
. Downside of this, you need to call this yourself so you can't use inheritance seamlessly. Good thing is you always get an implementation class so you can do DB stuff in the inherited method.
Pitfall, this breaks if you act silly and replace Parent
in the namespace:
ParentImpl = self.instance.register(Parent)
ChildImpl = self.instance.register(Child)
Parent = 'Let me try something stupid'
child = ChildImpl(name='Toto')
child.get_name()
from umongo.
Yeah, __init__
and super()
seems really hard to cleanly build from template to implementation.
From my point of view it's not such a big deal given a Document
rotate around it data from the database and so should not initialize anything but them.
However, we could create a special callback method (i.g. _on_init()
) that would be called when the document is initialized. This would solve the trouble and we could even create an error message in the builder when copying fields from template to implementation if we found an __init__
field.
from umongo.
From my point of view it's not such a big deal given a Document rotate around it data from the database and so should not initialize anything but them.
I don't understand this sentence.
However, we could create a special callback method (i.g. _on_init()) that would be called when the document is initialized.
Sure. Although you sometimes want more flexibility so you might need pre_init
and post_init
.
But __init__
is not the only method with an issue, is it?
I mean, sometimes, you want to override your own methods, like my get_name
example and I think this is also broken.
Here's an updated proposal, this time using super() and passing the class as a string to avoid relying on the namespace not being messed up with:
def test_super_in_inheritance(self):
class Parent(Document):
def get_impl_from_tmpl(self, tmpl):
return self.opts.instance.retrieve_document(tmpl)
class Meta:
allow_inheritance = True
name = fields.StrField()
def get_name(self):
return self.name
class Child(Parent):
def get_name(self):
name = super(self.get_impl_from_tmpl('Child'), self).get_name()
return name[0]
ParentImpl = self.instance.register(Parent)
ChildImpl = self.instance.register(Child)
child = ChildImpl(name='Toto')
child.get_name()
Using super()
this way lets it deal with multi-inheritance and complicated stuff I wouldn't like to screw up.
from umongo.
Another proposal with a _super
method:
def test_super_in_inheritance(self):
class Parent(Document):
def _super(self, tmpl):
return super(_get_impl_from_tmpl(self, tmpl))
def _get_impl_from_tmpl(self, tmpl):
return self.opts.instance.retrieve_document(tmpl)
class Meta:
allow_inheritance = True
name = fields.StrField()
def get_name(self):
return self.name
class Child(Parent):
def get_name(self):
name = self._super('Child').get_name()
return name[0]
ParentImpl = self.instance.register(Parent)
ChildImpl = self.instance.register(Child)
child = ChildImpl(name='Toto')
child.get_name()
Or with custom _super()
as a static method, to be as close as builtin super
as possible. But it's a bit of a pity to pass self
manually just so that it looks more like the builtin.
def test_super_in_inheritance(self):
class Parent(Document):
@staticmethod
def _super(tmpl, self):
return super(_get_impl_from_tmpl(self, tmpl))
def _get_impl_from_tmpl(self, tmpl):
return self.opts.instance.retrieve_document(tmpl)
class Meta:
allow_inheritance = True
name = fields.StrField()
def get_name(self):
return self.name
class Child(Parent):
def get_name(self):
name = self._super('Child', self).get_name()
return name[0]
ParentImpl = self.instance.register(Parent)
ChildImpl = self.instance.register(Child)
child = ChildImpl(name='Toto')
child.get_name()
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.