Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Database Features not set for Postgres for management commands #30

Closed
valentijnscholten opened this issue Apr 15, 2021 · 4 comments
Closed

Comments

@valentijnscholten
Copy link

Hi,

Yes, I have added django-jsonfield-backport to INSTALLED_APPS.

Might be that the cause of the below is somewhere else / somewhere upstream in django, but I am seeing the following.
I have an application that works find with a json field on a model. I can delete that model just fine from the UI that have build, running with runserver or uwsgi etc. It also runs fine if I try to delete model instances from a management command.

When I run the same application with postgres and runserver or uwsgi, it also works fine. I can delete model instances.
But when I run a management command to delete model instances, I get an exception:

  File "./manage.py", line 11, in <module>
    execute_from_command_line(sys.argv)
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/home/valentijn/dd/dojo/management/commands/test_valentijn5.py", line 10, in handle
    engagement.delete()
  File "/home/valentijn/dd/dojo/models.py", line 1042, in delete
    super().delete(*args, **kwargs)
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/db/models/base.py", line 921, in delete
    collector.collect([self], keep_parents=keep_parents)
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/db/models/deletion.py", line 224, in collect
    field.remote_field.on_delete(self, field, sub_objs, self.using)
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/db/models/deletion.py", line 15, in CASCADE
    collector.collect(sub_objs, source=field.remote_field.model,
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/db/models/deletion.py", line 223, in collect
    elif sub_objs:
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/db/models/query.py", line 278, in __bool__
    self._fetch_all()
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/db/models/query.py", line 1242, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/db/models/query.py", line 72, in __iter__
    for row in compiler.results_iter(results):
  File "/home/valentijn/venv/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1086, in apply_converters
    value = converter(value, expression, connection)
  File "/home/valentijn/venv/lib/python3.8/site-packages/django_jsonfield_backport/models.py", line 111, in from_db_value
    if connection.features.has_native_json_field and self.decoder is None:
AttributeError: 'DatabaseFeatures' object has no attribute 'has_native_json_field'

When debugging, it looks like the extend_features is not called in this scenario. Looking at the code of this backport it connects to the connection_created signal. For some reason this doesn't seem to be called when running as a management command against a postgres database. For MySQL it runs fine. As said, might be something upstream, but at least I can share my workaround here. I added the below to my management command to make it work:

from django_jsonfield_backport.features import extend_features
from django.db import connection

class Command(BaseCommand):

    def handle(self, *args, **options):
        extend_features(connection)
     
        .... do_stuff .... 

@laymonage
Copy link
Owner

Hi @valentijnscholten, thanks for the report! I'm afraid that's not something I can handle from my side. Maybe try creating a ticket to Django? The workaround seems logical, though. Thanks for sharing!

@josterpi
Copy link
Contributor

I am using MySQL and have run into this as well. In addition to management commands, ./manage.py shell also has this problem.

I dug into it and found that the connection_created signal is sent before extend_features gets registered in those cases, so it never ends up running.

I've created a pull request that calls extend_features(connection) if connection.is_usable() or registers the signal handler otherwise.

@laymonage
Copy link
Owner

Fixed in v1.0.5, please verify. Thanks!

@valentijnscholten
Copy link
Author

For the record, it's fixed in #39

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants