MongoEngine / MongoEngine/mongoengine

GenericEmbeddedDocumentField validation errors on .upsert but not on .save

Open
#2,543 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
4.3k
Forks
1.2k
Avg merge
4h 41m
Merged PRs (30d)
11

Description

Hi, I have a document defined with GenericEmbeddedDocumentField field;

class BrandItem(mg.Document):
    """

    BrandItems of a brand in the inventory

    """

    # inventory name of the brandItem
    name = StringField(required=True, unique_with='brand')

    # Brand under which the brandItems fall
    # If the brand is deleted this brand item will also be deleted
    brand = ReferenceField('Brand', reverse_delete_rule=CASCADE)

    # item type stores the type of items and item body stores the object of the type
    item_type = EnumField(ItemType, required=True)
    item_body = GenericEmbeddedDocumentField(required=True)

    # Auto update fields
    created = DateTimeField(default=datetime.utcnow())
    modified = DateTimeField()

    is_deleted = BooleanField(default=False)

When trying to save instances of this model I get different behaviours when creating an object and saving (works) and when trying to upsert it via the QuerySet manager (fails).

The error is

mongoengine.errors.ValidationError: Invalid embedded document instance provided to an GenericEmbeddedDocumentField

Interestingly, If I define the document with a DictField the behaviour swaps (upsert works and saves validation complains).

The upsert command:

    brand_item_dict = dict(
        name="Honey butter",
        brand=bid,
        is_excluded_from_gp_calculation=False,
        category_name="Condiments",
        item_type=ItemType.SUPPLIED_ITEM,
        item_body=SuppliedItem(
            purchasing_info=[
                    PurchasingInfo(
                        supplier="Nory Sup",
                        pack_size=5,
                        unit_of_measure=UnitOfMeasure.LITRE,
                        packs_per_case=10,
                        price=100,
                        currency=Currency.EURO,
                        price_unit_type=PriceUnitType.CASE,
                        is_main_purchasing_order_info=True,
                        supplier_code="item.supplier_code",
                )
            ]
        )

    )

    res = BrandItem.objects.upsert_one(
        **brand_item_dict
    )

The "same" command works when creating the brand object directly:

brand_item = BrandItem(
        name="Honey butter",
        brand=bid,
        is_excluded_from_gp_calculation=False,
        category_name="Condiments",
        item_type=ItemType.SUPPLIED_ITEM,
        item_body=SuppliedItem(
            purchasing_info=[
                    PurchasingInfo(
                        supplier="Nory Sup",
                        pack_size=5,
                        unit_of_measure=UnitOfMeasure.LITRE,
                        packs_per_case=10,
                        price=100,
                        currency=Currency.EURO,
                        price_unit_type=PriceUnitType.CASE,
                        is_main_purchasing_order_info=True,
                        supplier_code="item.supplier_code",
                )
            ]
        )

    )
    brand_item.save()

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the difference between QuerySet.upsert_one and Document.save with GenericEmbeddedDocumentField, using the BrandItem and SuppliedItem examples in the issue. Compare the validation behavior with DictField and determine what consistent validation result should be observed for both paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
mongodb, python
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.