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

Field ... of model container: ... cannot be of type "<class \'django.db.models.fields.related.ForeignKey\'>" #449

Open codot-fr opened 4 years ago

codot-fr commented 4 years ago

Hello,

I was using django 2.2.9 and djongo 1.3.0 and Python 3.6.4. I then upgraded packages to django 3.0.5 and djongo 1.3.3 with Python 3.8.5. I now have a exception raised at startup :

File "C:\Users\pjra835.virtualenvs\iaas_dashboard\lib\site-packages\djongo\models\fields.py", line 120, in _validate_container raise ValidationError( django.core.exceptions.ValidationError: ['Field "reporting.VirtualMachineQuote.region" of model container:"<class \'reporting.models.VirtualMachineQuote\'>" cannot be of type "<class \'django.db.models.fields.related.ForeignKey\'>"']

It comes from djongo models fields :

for field in self.model_container._meta._get_fields(reverse=False):
            if isinstance(field, (AutoField,
                                  BigAutoField,
                                  RelatedField)):
                raise ValidationError(
                    f'Field "{field}" of model container:"{self.model_container}" '
                    f'cannot be of type "{type(field)}"')

Why would a "RelatedField" field in a model raise en error ?

Python script

class Region(models.Model):
    name = models.CharField(max_length=30, verbose_name="Région")
    code = models.CharField(max_length=3, primary_key=True)

    def __str__(self):
        return self.name

    class Meta:
        pass

class VirtualMachineQuote(models.Model):
    OS_TYPES = [
        ("linux", "Linux"),
        ("windows", "Windows"),
    ]
    COMPUTE_TYPES = [
        ("shared", "Mutualisé"),
        ("dedicated", "Dédié"),
    ]
    STORAGE_TYPES = [
        ("resilient", "Résilient"),
        ("standard", "Standard"),
    ]
    description = models.CharField(max_length=250, verbose_name="Description")
    region = models.ForeignKey(Region, on_delete=models.SET_NULL, null=True, verbose_name="Région")
    os = models.CharField(max_length=50, choices=OS_TYPES, null=True)
    compute_type = models.CharField(max_length=50, choices=COMPUTE_TYPES, null=True)
    storage_type = models.CharField(max_length=50, choices=STORAGE_TYPES, null=True)
    cpu_count = models.IntegerField(default=1, verbose_name="Nombre de vCPUs")
    memory = models.IntegerField(default=1, verbose_name="Quantité de mémoire (Go)")
    hot_storage = models.IntegerField(default=20, verbose_name="Stockage chaud (Go)")
    cold_storage = models.IntegerField(default=0, blank=True, verbose_name="Stockage froid (Go)")

    class Meta:
        abstract = True

Traceback

C:\Users\pjra835\AppData\Local\JetBrains\Toolbox\apps\PyCharm-P\ch-0\201.8743.11\bin\runnerw64.exe C:\Users\pjra835\.virtualenvs\iaas_dashboard\Scripts\python.exe C:/Users/pjra835/PycharmProjects/iaas_dashboard/iaas_dashboard/manage.py runserver --noreload 8000 --insecure
Traceback (most recent call last):
  File "C:/Users/pjra835/PycharmProjects/iaas_dashboard/iaas_dashboard/manage.py", line 21, in <module>
    main()
  File "C:/Users/pjra835/PycharmProjects/iaas_dashboard/iaas_dashboard/manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\pjra835\.virtualenvs\iaas_dashboard\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "C:\Users\pjra835\.virtualenvs\iaas_dashboard\lib\site-packages\django\core\management\__init__.py", line 377, in execute
    django.setup()
  File "C:\Users\pjra835\.virtualenvs\iaas_dashboard\lib\site-packages\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\Users\pjra835\.virtualenvs\iaas_dashboard\lib\site-packages\django\apps\registry.py", line 114, in populate
    app_config.import_models()
  File "C:\Users\pjra835\.virtualenvs\iaas_dashboard\lib\site-packages\django\apps\config.py", line 211, in import_models
    self.models_module = import_module(models_module_name)
  File "C:\Users\pjra835\AppData\Local\Programs\Python\Python38-32\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "C:\Users\pjra835\PycharmProjects\iaas_dashboard\iaas_dashboard\reporting\models.py", line 313, in <module>
    class Quote(models.Model):
  File "C:\Users\pjra835\PycharmProjects\iaas_dashboard\iaas_dashboard\reporting\models.py", line 339, in Quote
    virtual_machines = models.ArrayField(
  File "C:\Users\pjra835\.virtualenvs\iaas_dashboard\lib\site-packages\djongo\models\fields.py", line 256, in __init__
    super().__init__(model_container, *args, **kwargs)
  File "C:\Users\pjra835\.virtualenvs\iaas_dashboard\lib\site-packages\djongo\models\fields.py", line 112, in __init__
    self._validate_container()
  File "C:\Users\pjra835\.virtualenvs\iaas_dashboard\lib\site-packages\djongo\models\fields.py", line 120, in _validate_container
    raise ValidationError(
django.core.exceptions.ValidationError: ['Field "reporting.VirtualMachineQuote.region" of model container:"<class \'reporting.models.VirtualMachineQuote\'>" cannot be of type "<class \'django.db.models.fields.related.ForeignKey\'>"']
mosi-kha commented 4 years ago

logically is correct, because in SQL ForeignKey reference to the table via PrimaryKey ... in this case, VirtualMachineQuote is abstract=True mean is not separate collection and you don't have a primary key.

codot-fr commented 4 years ago

But it was working previously. I omited this code, maybe it's related to a change in the usage of models.ArrayFields ?

` class VirtualMachineQuoteForm(forms.ModelForm): class Meta: model = VirtualMachineQuote fields = 'all'

class Quote(models.Model): STATUS_CHOICES = [ ("draft", "Brouillon"), ("locked", "Verrouillée") ]

status = models.CharField(max_length=50, choices=STATUS_CHOICES, default="draft")

project = models.ForeignKey(
    Project,
    on_delete=models.SET_NULL,
    null=True,
    related_name='quotes',
    blank=True,
    verbose_name="Projet"
)
user = models.ForeignKey(
    'users.User',
    on_delete=models.SET_NULL,
    null=True,
    related_name="Estimations",
    verbose_name="Utilisateur"
)
creation_date = models.DateTimeField(auto_now_add=True, null=True)
last_edit_date = models.DateTimeField(auto_now=True, null=True)
summary = models.CharField(max_length=250, verbose_name="Descriptif de la demande de devis")
virtual_machines = models.ArrayField(
    model_container=VirtualMachineQuote,
    model_form_class=VirtualMachineQuoteForm
)
backup_storage = models.ArrayField(
    model_container=BackupQuote,
    model_form_class=BackupQuoteForm
)
load_balancers = models.ArrayField(
    model_container=LoadBalancerQuote,
    model_form_class=LoadBalancerQuoteForm
)

def get_absolute_url(self):
    return reverse('quote-detail', kwargs={'pk': self.pk})

class QuoteForm(forms.ModelForm): class Meta: model = Quote fields = ( 'project', 'summary' ) `

mosi-kha commented 4 years ago

djongo is an unstable project and has no active comminute and contributor, it's so bad.