djongo icon indicating copy to clipboard operation
djongo copied to clipboard

No validation with Django >= 3.2.x

Open MiltosD opened this issue 3 years ago • 1 comments

One line description of the issue

Since Django 3.2.1 a check has been added to prevent instantiation of an abstract model. This seems to have broken the validation of a model instance with an EmbeddedField

django/db/models/base.py

# django/db/models/base.py

class Model(metaclass=ModelBase):

    def __init__(self, *args, **kwargs):
        # Alias some things as locals to avoid repeat global lookups
        cls = self.__class__
        opts = self._meta
        _setattr = setattr
        _DEFERRED = DEFERRED
        if opts.abstract:
            raise TypeError('Abstract models cannot be instantiated.')

Example

from django.core.validators import URLValidator
from djongo import models

class Address(models.Model):
    city = models.CharField(max_length=50)
    homepage = models.URLField(validators=[URLValidator])
    class Meta:
        abstract=True

class Entry(models.Model):
    _id = models.ObjectIdField()
    address = models.EmbeddedField(model_container=Address)

from entities.models import Entry e = Entry(address={'city': 'New York', 'homepage': 'http://mypage.com'}) e.clean_fields()

Traceback

Traceback (most recent call last): File "/usr/lib/python3.8/code.py", line 90, in runcode exec(code, self.locals) File "", line 1, in File "site-packages/django/db/models/base.py", line 1497, in clean_fields setattr(self, f.attname, f.clean(raw_value, self)) File "site-packages/django/db/models/fields/init.py", line 754, in clean value = self.to_python(value) File "site-packages/djongo/models/fields.py", line 261, in to_python value = self._value_thru_container(value) File "site-packages/djongo/models/fields.py", line 182, in _value_thru_container inst = self.model_container(**value) File "site-packages/django/db/models/base.py", line 465, in init raise TypeError("Abstract models cannot be instantiated.") TypeError: Abstract models cannot be instantiated.

MiltosD avatar Dec 05 '22 08:12 MiltosD

I managed to instantiate by declaring the model as managed = False in the Meta class and leaving abstract to False. What this does, is that it actually creates a migration operation for the model but does not create the collection, which, effectively is the same behavior as setting abstract = True. However, according to the Django docs, the purpose of managed = False is different, so I'm seeing this as a temporary solution...

MiltosD avatar Dec 07 '22 20:12 MiltosD