AbdealiLoKo
AbdealiLoKo

Reputation: 3317

Mongoengine - get where the object is referred

I'm trying out mongoengine in flask (python). And was trying to create a One-to-One field.

I have a model User and also models for types of Users like Author, Buyer, etc. Here's a simple version of my models:

class User(db.Document):
    username = db.StringField()
    password = db.StringField()

class Author(db.Document):
    books = db.ListField(db.StringField())
    user = db.ReferenceField(document_type=User, required=True)

Now, I can get the user from the author by simply

a = author.objects.all()[0] # Or get author through some other method
a.user

But if I have a user how do I get the author ?

u = user.objects.all()[0]
u.get_author() # ???

I know I can do Author.objects.get(user=u) but I was wondering if this can be done without an extra query.

Upvotes: 2

Views: 3856

Answers (1)

Steve Rossiter
Steve Rossiter

Reputation: 2925

Your User documents are stored in a separate collection with no reference to the Author collection so there is no way to do this without an extra query. You have some options that may make this process easier:

Add an author property to the User class:

class User(db.Document):
    username = db.StringField()
    password = db.StringField()

    @property
    def author(self):
        return Author.objects(user=self).get()

class Author(db.Document):
    books = db.ListField(db.StringField())
    user = db.ReferenceField(document_type=User, required=True)

This will allow you to do:

u = User.objects.first()
print(u.author.books)

However, it seems that in this context where author is just a special type of User then you should use document inheritance, for example:

class User(db.Document):
    username = db.StringField()
    password = db.StringField()

    meta = {'allow_inheritance': True}

class Author(User):
    books = db.ListField(db.StringField())

a = Author(username="dr_seuss", password="sneech16", 
           books=["Green Eggs and Ham","The Cat in the Hat"])
a.save()

This will allow you to query by either Author or User:

>>> Author.objects.first().username
'dr_seuss'

>>> User.objects.first().username
'dr_seuss'

Upvotes: 2

Related Questions