A generic embedded document field - allows any :class:`~mongoengine.EmbeddedDocument` to be stored. Only valid values are subclasses of :class:`~mongoengine.EmbeddedDocument`. .. note :: You can use the choices param to limit the acceptable EmbeddedDocument types
| 791 | |
| 792 | |
| 793 | class GenericEmbeddedDocumentField(BaseField): |
| 794 | """A generic embedded document field - allows any |
| 795 | :class:`~mongoengine.EmbeddedDocument` to be stored. |
| 796 | |
| 797 | Only valid values are subclasses of :class:`~mongoengine.EmbeddedDocument`. |
| 798 | |
| 799 | .. note :: |
| 800 | You can use the choices param to limit the acceptable |
| 801 | EmbeddedDocument types |
| 802 | """ |
| 803 | |
| 804 | def prepare_query_value(self, op, value): |
| 805 | return super().prepare_query_value(op, self.to_mongo(value)) |
| 806 | |
| 807 | def to_python(self, value): |
| 808 | if isinstance(value, dict): |
| 809 | doc_cls = get_document(value["_cls"]) |
| 810 | value = doc_cls._from_son(value) |
| 811 | |
| 812 | return value |
| 813 | |
| 814 | def validate(self, value, clean=True): |
| 815 | if self.choices and isinstance(value, SON): |
| 816 | for choice in self.choices: |
| 817 | if value["_cls"] == choice._class_name: |
| 818 | return True |
| 819 | |
| 820 | if not isinstance(value, EmbeddedDocument): |
| 821 | self.error( |
| 822 | "Invalid embedded document instance provided to an " |
| 823 | "GenericEmbeddedDocumentField" |
| 824 | ) |
| 825 | |
| 826 | value.validate(clean=clean) |
| 827 | |
| 828 | def lookup_member(self, member_name): |
| 829 | document_choices = self.choices or [] |
| 830 | for document_choice in document_choices: |
| 831 | doc_and_subclasses = [document_choice] + document_choice.__subclasses__() |
| 832 | for doc_type in doc_and_subclasses: |
| 833 | field = doc_type._fields.get(member_name) |
| 834 | if field: |
| 835 | return field |
| 836 | |
| 837 | def to_mongo(self, document, use_db_field=True, fields=None): |
| 838 | if document is None: |
| 839 | return None |
| 840 | data = document.to_mongo(use_db_field, fields) |
| 841 | if "_cls" not in data: |
| 842 | data["_cls"] = document._class_name |
| 843 | return data |
| 844 | |
| 845 | |
| 846 | class DynamicField(BaseField): |