I have two objects that are related to one another. I'd like to be able to access one object through the other by going through the related attribute.
E.g. A.b_relationship.obj.some_property
How can I do this without creating a circular import?
# lib.py
class Relationship(object):
def __init__(self, obj):
self.obj = obj
# a.py
class A(object):
b_relationship = Relationship(B)
# b.py
class B(object):
a_relationship = Relationship(A)
For clarity, I've added this additional example. Obviously SQLAlchemy has solved this issue with the backref
attribute. I'm not sure how feasible it would be for me to implement this sort of thing into marshmallow without breaking the way it works. Perhaps I need to change my mindset?
from marshmallow import Schema
from marshmallow.fields import String
from project.database import db
class PersonModel(db.Model):
name = db.Column(db.String)
class PetModel(db.Model):
name = db.Column(db.String)
owner = db.relationship('PersonModel', backref='pets')
class PersonSchema(Schema):
name = fields.String(init_arg='some value')
pets = fields.Relationship(related_schema=PetSchema)
class PetSchema(Schema):
name = fields.String()
owner = fields.Relationship(related_schema=PersonSchema)
From here: http://marshmallow.readthedocs.org/en/latest/nesting.html#two-way-nesting
See how a string is used for the class; AuthorSchema refers to 'BookSchema':
class AuthorSchema(Schema):
# Make sure to use the 'only' or 'exclude' params
# to avoid infinite recursion
books = fields.Nested('BookSchema', many=True, exclude=('author', ))
class Meta:
fields = ('id', 'name', 'books')
class BookSchema(Schema):
author = fields.Nested(AuthorSchema, only=('id', 'name'))
class Meta:
fields = ('id', 'title', 'author')
I assume in your case, you want to do the same thing with many=False
. I've never used marshmallow but in Django, it's similar, we use class path like "my_app.MyClass" instead of MyClass
to avoid circular import.
You could implement a RelationshipManager
(aka a registry), which all classes that can be part of a relationship must be registered with.
The Relationship
initialiser could take then the name of the class it's related to, rather than the actual class object.
Finally, the relationship class itself can lazy-load the real class it's related to from the name it's given at initialisation (via the manager).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With