Skip to content

Commit a494e6a

Browse files
committed
Update docs
1 parent 811defa commit a494e6a

File tree

5 files changed

+92
-30
lines changed

5 files changed

+92
-30
lines changed

docs/howto/queryable-encryption.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ encrypted database in your :setting:`django:DATABASES` setting.
4141

4242
This database will be used to store encrypted fields in your models. The
4343
following example shows how to configure an encrypted database using the
44-
:class:`pymongo.encryption_options.AutoEncryptionOpts` from the
45-
:mod:`pymongo.encryption_options` module.
44+
:class:`AutoEncryptionOpts <pymongo.encryption_options.AutoEncryptionOpts>` from the
45+
:mod:`encryption_options <pymongo.encryption_options>` module.
4646

4747
This example uses a local KMS provider and a key vault namespace for storing
4848
encryption keys.
@@ -188,6 +188,7 @@ Example of KMS configuration with AWS KMS:
188188
def kms_provider(self, model, **hints):
189189
return "aws"
190190
191+
.. _qe-configuring-encrypted-fields-map:
191192

192193
Configuring the ``encrypted_fields_map``
193194
========================================

docs/ref/django-admin.rst

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,32 @@ Available commands
2222
.. django-admin:: showencryptedfieldsmap
2323

2424
This command shows the mapping of encrypted fields to attributes including
25-
data type, data keys and query types. It can be used to set the
26-
``encrypted_fields_map`` in ``AutoEncryptionOpts``.
25+
data type, data keys and query types. Its output can be used to set the
26+
:ref:`encrypted_fields_map <qe-configuring-encrypted-fields-map>` argument
27+
in :class:`AutoEncryptionOpts
28+
<pymongo.encryption_options.AutoEncryptionOpts>`.
2729

2830
.. django-admin-option:: --database DATABASE
2931

3032
Specifies the database to use. Defaults to ``default``.
33+
34+
To show the encrypted fields map for a database named ``encrypted``, run:
35+
36+
.. code-block:: console
37+
38+
$ python manage.py showencryptedfieldsmap --database encrypted
39+
{
40+
"myapp.mymodel": {
41+
"encrypted_field_1": {
42+
"bsonType": "string",
43+
"keyId": "UUID('...')",
44+
"queries": ["equality", "range"]
45+
},
46+
"encrypted_field_2": {
47+
"bsonType": "int",
48+
"keyId": "UUID('...')",
49+
"queries": ["equality"]
50+
}
51+
},
52+
...
53+
}

docs/ref/utils.rst

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,52 @@ following parts can be considered stable.
4848

4949
But for maximum flexibility, construct :setting:`DATABASES` manually as
5050
described in :ref:`configuring-databases-setting`.
51+
52+
.. versionadded:: 5.2.3
53+
54+
``model_has_encrypted_fields()``
55+
=================================
56+
57+
.. function:: model_has_encrypted_fields(model)
58+
59+
Returns ``True`` if the given Django model has any fields that use
60+
encrypted models.
61+
62+
Example::
63+
64+
from django_mongodb_backend.utils import model_has_encrypted_fields
65+
from myapp.models import MyModel
66+
67+
if model_has_encrypted_fields(MyModel):
68+
print("MyModel has encrypted fields")
69+
else:
70+
print("MyModel does not have encrypted fields")
71+
72+
73+
Example usage in a database router::
74+
75+
from django_mongodb_backend.utils import model_has_encrypted_fields
76+
77+
class EncryptedRouter:
78+
def db_for_read(self, model, **hints):
79+
if model_has_encrypted_fields(model):
80+
return "encrypted"
81+
return "default"
82+
83+
def db_for_write(self, model, **hints):
84+
if model_has_encrypted_fields(model):
85+
return "encrypted"
86+
return "default"
87+
88+
def allow_migrate(self, db, app_label, model_name=None, **hints):
89+
if hints.get("model"):
90+
if model_has_encrypted_fields(hints["model"]):
91+
return db == "encrypted"
92+
else:
93+
return db == "default"
94+
return None
95+
96+
def kms_provider(self, model):
97+
if model_has_encrypted_fields(model):
98+
return "local"
99+
return None

docs/topics/known-issues.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ Model fields
2626
- :class:`~django.db.models.CompositePrimaryKey`
2727
- :class:`~django.db.models.GeneratedField`
2828

29+
.. _known-issues-limitations-querying:
30+
2931
Querying
3032
========
3133

docs/topics/queryable-encryption.rst

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ queries on certain encrypted fields. To use encrypted fields in your models,
2121
import the necessary field types from ``django_mongodb_backend.models`` and
2222
define your models as usual.
2323

24+
Here's the `Python Queryable Encryption Tutorial`_ example implemented in
25+
Django:
26+
2427
.. code-block:: python
2528
2629
# myapp/models.py
@@ -94,8 +97,10 @@ query type in the model field definition. For example, if you want to query the
9497
billing = EncryptedEmbeddedModelField("Billing")
9598
bill_amount = models.DecimalField(max_digits=10, decimal_places=2)
9699
97-
Query types
98-
~~~~~~~~~~~
100+
.. _qe-available-query-types:
101+
102+
Available query types
103+
~~~~~~~~~~~~~~~~~~~~~
99104

100105
The ``queries`` option should be a dictionary that specifies the type of queries
101106
that can be performed on the field. The :ref:`available query types
@@ -116,30 +121,12 @@ For example, to find a patient by their SSN, you can do the following::
116121
>>> patient.name
117122
'Bob'
118123

119-
120124
QuerySet limitations
121125
~~~~~~~~~~~~~~~~~~~~
122126

123-
When using Django QuerySets with MongoDB Queryable Encryption, it’s important to
124-
understand that many typical ORM features are restricted because the database
125-
only sees encrypted ciphertext, not plaintext. This means that only certain
126-
query types are supported, and a lot of filtering, sorting, and aggregating must
127-
be done client-side after decryption. Key limitations include:
128-
129-
- **Equality only filtering** – You can filter encrypted fields using exact
130-
matches, but operators like contains, startswith, regex, or unsupported range
131-
lookups will not work.
132-
- **No server-side sorting** – .order_by() on encrypted fields won’t produce
133-
meaningful results; sorting needs to happen after decryption in Python.
134-
- **No server-side aggregation** – Functions like annotate() or aggregate()
135-
won’t operate on encrypted fields; you must aggregate locally after fetching
136-
data.
137-
- **Index constraints** – Queries are only possible on encrypted fields that
138-
have a configured queryable encryption index and keys available on the client.
139-
- **No joins on encrypted fields** – Filtering across relationships using
140-
encrypted foreign keys is unsupported because matching must happen
141-
client-side.
142-
143-
In short, when working with Queryable Encryption, design your queries to use
144-
exact matches only on encrypted fields, and plan to handle any sorting or
145-
aggregation after results are decrypted in your application code.
127+
In addition to :ref:`Django MongoDB Backend's QuerySet limitations
128+
<known-issues-limitations-querying>`,
129+
130+
.. TODO
131+
132+
.. _Python Queryable Encryption Tutorial: https://github.com/mongodb/docs/tree/main/content/manual/manual/source/includes/qe-tutorials/python

0 commit comments

Comments
 (0)