mongoengine icon indicating copy to clipboard operation
mongoengine copied to clipboard

GenericEmbeddedDocumentField validation errors on .upsert but not on .save

Open osnory opened this issue 4 years ago • 0 comments

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()

osnory avatar Jul 29 '21 08:07 osnory