Code Monkey home page Code Monkey logo

django-mongodb's Issues

QuerySet.update() only updates one document if the field is unique

See comment.

A failing test (target is a field with unique=True):

    def test_multiple_unique(self):
        a_foo = Foo.objects.create(target="aaa")
        b_foo = Foo.objects.create(target="bbb")
        Foo.objects.update(target="ccc")
        a_foo.refresh_from_db()
        b_foo.refresh_from_db()
        self.assertEqual(a_foo.target, "ccc")
        self.assertEqual(b_foo.target, "ccc")

======================================================================
FAIL: test_multiple_unique (update.tests.AdvancedTests.test_multiple_unique)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/tests/update/tests.py", line 153, in test_multiple_unique
    self.assertEqual(b_foo.target, "ccc")
AssertionError: 'bbb' != 'ccc'
- bbb
+ ccc

Cannot force an update in save() with no primary key.

Hey all,

Not sure if you are looking for feedback, but FYI testing this with my Django setup and getting Cannot force an update in save() with no primary key. on update_fields = frozenset({'last_login'}).

False False frozenset({'last_login'})
Internal Server Error: /django/login/
Traceback (most recent call last):
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/views/decorators/cache.py", line 80, in _view_wrapper
    response = view_func(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/contrib/admin/sites.py", line 440, in login
    return LoginView.as_view(**defaults)(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/views/decorators/debug.py", line 143, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/utils/decorators.py", line 188, in _view_wrapper
    result = _process_exception(request, e)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/utils/decorators.py", line 186, in _view_wrapper
    response = view_func(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/views/decorators/cache.py", line 80, in _view_wrapper
    response = view_func(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/contrib/auth/views.py", line 88, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 143, in dispatch
    return handler(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/views/generic/edit.py", line 151, in post
    return self.form_valid(form)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/contrib/auth/views.py", line 107, in form_valid
    auth_login(self.request, form.get_user())
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/contrib/auth/__init__.py", line 152, in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/dispatch/dispatcher.py", line 189, in send
    response = receiver(signal=self, sender=sender, **named)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/contrib/auth/models.py", line 23, in update_last_login
    user.save(update_fields=["last_login"])
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/contrib/auth/base_user.py", line 78, in save
    super().save(*args, **kwargs)
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/db/models/base.py", line 822, in save
    self.save_base(
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/db/models/base.py", line 909, in save_base
    updated = self._save_table(
              ^^^^^^^^^^^^^^^^^
  File "/Users/alexclark/Developer/test/test-django-mongodb/.venv/lib/python3.12/site-packages/django/db/models/base.py", line 1016, in _save_table
    raise ValueError("Cannot force an update in save() with no primary key.")
ValueError: Cannot force an update in save() with no primary key.
[12/Jun/2024 17:47:59] "POST /django/login/?next=/django/ HTTP/1.1" 500 286725
Not Found: /favicon.ico
[12/Jun/2024 17:47:59] "GET /favicon.ico HTTP/1.1" 404 15933

In the event this is not a known issue I'm interested in looking into it, if anyone would like to provide some feedback or direction. ๐Ÿ˜„ Thank you

NotSupportedError: Ordering can't span tables on MongoDB (content_type__app_label)

Steps to reproduce

Followed instructions for initial setup from #18. Created my first admin account. From there, I called python manage.py makemigrations which worked. Afterward I then called python manage.py migrate which led to this initial error.

python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying admin.0004_alter_logentry_id... OK
  Applying auth.0013_alter_group_id_alter_permission_id_alter_user_id... OK
  Applying contenttypes.0003_alter_contenttype_id... OK
Traceback (most recent call last):
  File "/Users/jib/mongo/starterapp/storefront/manage.py", line 22, in <module>
    main()
  File "/Users/jib/mongo/starterapp/storefront/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/core/management/base.py", line 413, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/core/management/base.py", line 459, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/core/management/base.py", line 107, in wrapper
    res = handle_func(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/core/management/commands/migrate.py", line 383, in handle
    emit_post_migrate_signal(
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/core/management/sql.py", line 52, in emit_post_migrate_signal
    models.signals.post_migrate.send(
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/dispatch/dispatcher.py", line 189, in send
    response = receiver(signal=self, sender=sender, **named)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/contrib/auth/management/__init__.py", line 91, in create_permissions
    all_perms = set(
                ^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/query.py", line 400, in __iter__
    self._fetch_all()
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/query.py", line 1928, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django_mongodb/compiler.py", line 47, in results_iter
    results = self.build_query(columns).fetch()
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django_mongodb/compiler.py", line 140, in build_query
    query.order_by(self._get_ordering())
                   ^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django_mongodb/compiler.py", line 170, in _get_ordering
    raise NotSupportedError("Ordering can't span tables on MongoDB (%s)." % order)
django.db.utils.NotSupportedError: Ordering can't span tables on MongoDB (content_type__app_label).

add support for GenericForeignKey and GenericRelation

Supporting Django's GenericForeignKey and GenericRelation requires defining two other fields on the model: object_id and content_type:

class TaggedItem(models.Model):
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey("content_type", "object_id")

For MongoDB, however, object_id must store an ObjectId corresponding to the related object's primary key rather than an integer corresponding to a numeric primary key.

Thus far, I have changed instance of object_id = models.PositiveIntegerField() in Django's test suite to object_id = models.CharField(max_length=24) and haven't encountered any problems. While triaging aggregation_regress.tests.AggregationTests.test_aggregation_with_generic_reverse_relation (currently listed in expected failures), however, @WaVEV suggested object_id may need to be defined using a new ObjectIdField for it to work.

That said, the admin's LogEntry model uses object_id = models.TextField(_("object id"), blank=True, null=True), so if there are limitations with this approach, we should be aware.

Django test app: generic_relations

implement SchemaEditor.add/alter/remove_field()

Should these operations try to follow what Django does on SQL backends as much as possible?

For example, if adding a field with a default, Django will populate the default value on existing rows. Should MongoDB do it? If so, what about if there's no value to be populated? Should the field not be added to existing documents? We might be able to do that for nullable fields, but perhaps not for string-based fields where null=False and the default is an empty string.

add support for QuerySet.select_related()

Steps to reproduce

Successfully created a superuser. Once I created a superuser I attempted to work through the admin page. This then failed with the error QuerySet.select_related() is not supported.

<pre class="exception_value" style="padding: 0px; margin: 10px 0px; font-size: 1.5em; white-space: pre-wrap; word-break: break-word; font-family: sans-serif; color: rgb(87, 87, 87); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">QuerySet.select_related() is not supported on MongoDB.</pre>
Request Method: | GET
-- | --
http://127.0.0.1:8000/admin/
5.0.6
NotSupportedError
QuerySet.select_related() is not supported on MongoDB.
/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django_mongodb/compiler.py, line 113, in check_query
django.contrib.admin.sites.index
/opt/homebrew/Caskroom/miniforge/base/envs/django/bin/python
3.12.3
['/Users/jib/mongo/starterapp/storefront',  '/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python312.zip',  '/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12',  '/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/lib-dynload',  '/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages']

Environment

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/admin/

Django Version: 5.0.6
Python Version: 3.12.3
Installed Applications:
['apps.MongoAdminConfig',
 'apps.MongoAuthConfig',
 'apps.MongoContentTypesConfig',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'playground']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']

implement dbshell

django_mongodb/client.py is stubbed out, but DatabaseClient.settings_to_cmd_args_env() needs to be implemented to construct the connection arguments for the mongo shell.

mongod crashes while running the Django test suite

For example, mongod terminates with "Aborted (core dumped)" in the middle of $ ./runtests.py sessions_tests or $ ./runtests.py lookup. It may be a problem specific to my environment (Ubuntu 20.04) as it has not happened while running the tests on GitHub actions.

$ mongod --version
db version v7.0.8
Build Info: {
    "version": "7.0.8",
    "gitVersion": "c5d33e55ba38d98e2f48765ec4e55338d67a4a64",
    "openSSLVersion": "OpenSSL 1.1.1f  31 Mar 2020",
    "modules": [],
    "allocator": "tcmalloc",
    "environment": {
        "distmod": "ubuntu2004",
        "distarch": "x86_64",
        "target_arch": "x86_64"
    }
}

Add a "not supported error" (instead of crashing) for QuerySet.aggregate()

For example:

./tests/runtests.py from_db_value.tests.FromDBValueTest.test_aggregation
Testing against Django installed in '/home/tim/code/django/django' with up to 3 processes
Found 1 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E
======================================================================
ERROR: test_aggregation (from_db_value.tests.FromDBValueTest.test_aggregation)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/tests/from_db_value/tests.py", line 26, in test_aggregation
    maximum = CashModel.objects.aggregate(m=Max("cash"))["m"]
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/tim/code/django/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/tim/code/django/django/db/models/query.py", line 604, in aggregate
    return self.query.chain().get_aggregation(self.db, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/tim/code/django/django/db/models/sql/query.py", line 620, in get_aggregation
    result = next(compiler.apply_converters((result,), converters))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/tim/code/django/django/db/models/sql/compiler.py", line 1500, in apply_converters
    value = converter(value, expression, connection)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/tim/code/django-mongodb/django_mongodb/operations.py", line 38, in convert_decimalfield_value
    value = decimal.Decimal(value)
            ^^^^^^^^^^^^^^^^^^^^^^
TypeError: conversion from dict to Decimal is not supported

It's probably complicated (impossible?) to implement full aggregate support, but for now it should not crash.

add JSONField support

Remove DatabaseFeatures.supports_json_field = False and work on fixing as much of tests/model_fields/test_jsonfield.py as possible.

refactor MongoQuery.add_filters()

Jib: We should cut a task to break up and simplify this function. It's far too lengthy and confusing, especially as we get into the negation logic. It isn't encapsulated well, so it gets hard to remember what was happening previously.

Saving twice causes TypeError: Field 'id' expected a number but got ObjectId

Context

after running python mange.py shell I attempted to query the database I just collected.

>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
>>> q.save()
>>> q.id
ObjectId('66b24df05ad79637c54da774')
>>> q.question_text = "What's up"
>>> q.save()
Traceback (most recent call last):
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/fields/__init__.py", line 2117, in get_prep_value
    return int(value)
           ^^^^^^^^^^
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'ObjectId'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/base.py", line 822, in save
    self.save_base(
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/base.py", line 909, in save_base
    updated = self._save_table(
              ^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/base.py", line 1040, in _save_table
    updated = self._do_update(
              ^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/base.py", line 1084, in _do_update
    filtered = base_qs.filter(pk=pk_val)
               ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/query.py", line 1476, in filter
    return self._filter_or_exclude(False, args, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/query.py", line 1494, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/query.py", line 1501, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/sql/query.py", line 1613, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/sql/query.py", line 1645, in _add_q
    child_clause, needed_inner = self.build_filter(
                                 ^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/sql/query.py", line 1559, in build_filter
    condition = self.build_lookup(lookups, col, value)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/sql/query.py", line 1389, in build_lookup
    lookup = lookup_class(lhs, rhs)
             ^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/lookups.py", line 30, in __init__
    self.rhs = self.get_prep_lookup()
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/lookups.py", line 364, in get_prep_lookup
    return super().get_prep_lookup()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/lookups.py", line 88, in get_prep_lookup
    return self.lhs.output_field.get_prep_value(self.rhs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/miniforge/base/envs/django/lib/python3.12/site-packages/django/db/models/fields/__init__.py", line 2119, in get_prep_value
    raise e.__class__(
TypeError: Field 'id' expected a number but got ObjectId('66b24df05ad79637c54da774').
>>> q.save()

When I check the database I do see the value, and running this yields:

>>> Question.objects.all().values()
<QuerySet [{'id': None, 'question_text': "What's new?", 'pub_date': datetime.datetime(2024, 8, 6, 16, 23, 10, 65000, tzinfo=datetime.timezone.utc)}]>

Count() in QuerySet.annotate() crashes: Unknown expression $count

QuerySet: Author.objects.annotate(c=Count("id"))

SQL:

SELECT "annotations_author"."id",
       "annotations_author"."name",
       "annotations_author"."age",
       COUNT("annotations_author"."id") AS "c"
FROM "annotations_author"
GROUP BY "annotations_author"."id",
         "annotations_author"."name",
         "annotations_author"."age"

MQL:
{'$project': {'_id': 1, 'name': 1, 'age': 1, 'c': {'$count': ['$_id']}}}
Error:
pymongo.errors.OperationFailure: Invalid $project :: caused by :: Unknown expression $count,

If the query can't be expressed correctly, django-mongodb should raise a helpful NotSupportedError, and the limitation should be documented in the README.

querying the reverse side of a foreign key for null returns no results

======================================================================
FAIL: test_filter_one_to_one_relations (one_to_one.tests.OneToOneTests.test_filter_one_to_one_relations)
Regression test for #9968
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/tests/one_to_one/tests.py", line 318, in test_filter_one_to_one_relations
    self.assertSequenceEqual(Target.objects.filter(pointer=None), [target])
AssertionError: Sequences differ: <QuerySet []> != [<Target: Target object (668ff1f6b15ecc9d68b8404f)>]

Second sequence contains 1 additional elements.
First extra element 0:
<Target: Target object (668ff1f6b15ecc9d68b8404f)>

- <QuerySet []>
+ [<Target: Target object (668ff1f6b15ecc9d68b8404f)>]

QuerySet: Target.objects.filter(pointer=None)

SQL:

SELECT "one_to_one_target"."id",
       "one_to_one_target"."name"
FROM "one_to_one_target"
LEFT OUTER JOIN "one_to_one_pointer" ON ("one_to_one_target"."id" = "one_to_one_pointer"."other_id")
WHERE "one_to_one_pointer"."other_id" IS NULL;

MQL:

one_to_one_target.aggregate([
    {
        '$lookup': {
            'from': 'one_to_one_pointer',
            'let': {'parent__field__0': '$_id'},
            'pipeline': [
                {'$match': {'$expr': {'$and': [{'$eq': ['$$parent__field__0', '$other_id']}]}}}
            ],
            'as': 'one_to_one_pointer'
        }
    },
    {
        '$set': {
            'one_to_one_pointer': {
                '$cond': {
                    'if': {
                        '$or': [
                            {'$eq': [{'$type': '$one_to_one_pointer'}, 'missing']},
                            {'$eq': [{'$size': '$one_to_one_pointer'}, 0]}
                        ]
                    },
                    'then': [{}],
                    'else': '$one_to_one_pointer'
                }
            }
        }
    },
    {'$unwind': '$one_to_one_pointer'},
    {'$match': {'$expr': {'$eq': ['$one_to_one_pointer.other_id', None]}}}
]);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.