doableware / djongo

Django and MongoDB database connector
https://www.djongomapper.com
GNU Affero General Public License v3.0
1.88k stars 355 forks source link

No validation with Django >= 3.2.x #649

Open MiltosD opened 1 year ago

MiltosD commented 1 year ago

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

```python # 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 ```python 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 commented 1 year ago

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...