0

I have a base document class Feed from which RSS and Channels inherit. Here is the definition:

class Feed(Document):
    meta_info = EmbeddedDocument(MetaInfo, default=MetaInfo, required=True)
    name = StringField()
    link = StringField()

    meta = {'allow_inheritance': True}

I want my two other classes, RSS and Channels, to be able to inherit the Feed document with its embedded document MetaInfo. However, when the whole file is run, alongside the following code:

class Channel(Feed):
    channel_id = IntField(primary_key=True, unique=True, required=True)
    update_interval = IntField(default=300, required=True)

# similar class for RSS but with different fields

I get the following error:

  File "/Users/komron/dev/github/courant/src/models/channels.py", line 9, in <module>
    class Channel(Feed):
  File "/Users/komron/.local/share/virtualenvs/courant-Dv7-v42z/lib/python3.7/sitepackages/mongoengine/base/metaclasses.py", line 407, in __new__
    raise ValueError("Cannot override primary key field")
ValueError: Cannot override primary key field

What am I doing wrong? Are there any restrictions placed on inheritance with MongoEngine that I should be aware of? Thanks.

Sergey Ronin
  • 756
  • 7
  • 23

1 Answers1

2

Since you use inheritance, both Feed, RSS and Channels classes' documents will live in the same collection (named feed by default). The problem is that you can't have multiple primary keys within 1 collection, your subclasses need to share the same field that is defined as primary key and it should be defined in the parent Feed class.

Note that when you don't specify anything (like in your Feed class), MongoEngine implicitly uses id=ObjectIdField(primary_key=True, default=bson.ObjectId) behind the scenes. This explains why you get an error related to overriding it.

This SO post related to primary key might also be of interest

bagerard
  • 5,681
  • 3
  • 24
  • 48
  • I'd like to keep the two objects in different feeds though. Is that possible? – Sergey Ronin Jan 13 '20 at 09:12
  • If you want to keep the RSS and Channels in separate collections, then you can use the abstract classes concept (http://docs.mongoengine.org/guide/defining-documents.html#abstract-classes). – bagerard Jan 13 '20 at 12:20