Skip to content

Commit e1586f4

Browse files
committed
Revised README
1 parent 11754df commit e1586f4

File tree

2 files changed

+374
-183
lines changed

2 files changed

+374
-183
lines changed

DEV_NOTES.md

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# Developer Details
2+
3+
### Specifying the default primary key field
4+
5+
In your Django settings, you must specify that all models should use
6+
`ObjectIdAutoField`.
7+
8+
You can create a new project that's configured based on these steps using a
9+
project template:
10+
11+
```bash
12+
$ django-admin startproject mysite --template https://github.com/mongodb-labs/django-mongodb-project/archive/refs/heads/5.0.x.zip
13+
```
14+
(where "5.0" matches the version of Django that you're using.)
15+
16+
This template includes the following line in `settings.py`:
17+
18+
```python
19+
DEFAULT_AUTO_FIELD = "django_mongodb_backend.fields.ObjectIdAutoField"
20+
```
21+
22+
But this setting won't override any apps that have an `AppConfig` that
23+
specifies `default_auto_field`. For those apps, you'll need to create a custom
24+
`AppConfig`.
25+
26+
For example, the project template includes `<project_name>/apps.py`:
27+
28+
```python
29+
from django.contrib.admin.apps import AdminConfig
30+
from django.contrib.auth.apps import AuthConfig
31+
from django.contrib.contenttypes.apps import ContentTypesConfig
32+
33+
34+
class MongoAdminConfig(AdminConfig):
35+
default_auto_field = "django_mongodb_backend.fields.ObjectIdAutoField"
36+
37+
38+
class MongoAuthConfig(AuthConfig):
39+
default_auto_field = "django_mongodb_backend.fields.ObjectIdAutoField"
40+
41+
42+
class MongoContentTypesConfig(ContentTypesConfig):
43+
default_auto_field = "django_mongodb_backend.fields.ObjectIdAutoField"
44+
```
45+
46+
Each app reference in the `INSTALLED_APPS` setting must point to the
47+
corresponding ``AppConfig``. For example, instead of `'django.contrib.admin'`,
48+
the template uses `'<project_name>.apps.MongoAdminConfig'`.
49+
50+
### Configuring migrations
51+
52+
Because all models must use `ObjectIdAutoField`, each third-party and contrib app
53+
you use needs to have its own migrations specific to MongoDB.
54+
55+
For example, `settings.py` in the project template specifies:
56+
57+
```python
58+
MIGRATION_MODULES = {
59+
"admin": "mongo_migrations.admin",
60+
"auth": "mongo_migrations.auth",
61+
"contenttypes": "mongo_migrations.contenttypes",
62+
}
63+
```
64+
65+
The project template includes these migrations, but you can generate them if
66+
you're setting things up manually or if you need to create migrations for
67+
third-party apps. For example:
68+
69+
```console
70+
$ python manage.py makemigrations admin auth contenttypes
71+
Migrations for 'admin':
72+
mongo_migrations/admin/0001_initial.py
73+
- Create model LogEntry
74+
...
75+
```
76+
77+
### Creating Django applications
78+
79+
Whenever you run `python manage.py startapp`, you must remove the line:
80+
81+
`default_auto_field = 'django.db.models.BigAutoField'`
82+
83+
from the new application's `apps.py` file (or change it to reference
84+
`"django_mongodb_backend.fields.ObjectIdAutoField"`).
85+
86+
Alternatively, you can use the following `startapp` template which includes
87+
this change:
88+
89+
```bash
90+
$ python manage.py startapp myapp --template https://github.com/mongodb-labs/django-mongodb-app/archive/refs/heads/5.0.x.zip
91+
```
92+
(where "5.0" matches the version of Django that you're using.)
93+
94+
### Configuring the `DATABASES` setting
95+
96+
After you've set up a project, configure Django's `DATABASES` setting similar
97+
to this:
98+
99+
```python
100+
DATABASES = {
101+
"default": {
102+
"ENGINE": "django_mongodb_backend",
103+
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
104+
"NAME": "my_database",
105+
"USER": "my_user",
106+
"PASSWORD": "my_password",
107+
"PORT": 27017,
108+
"OPTIONS": {
109+
# Example:
110+
"retryWrites": "true",
111+
"w": "majority",
112+
"tls": "false",
113+
},
114+
},
115+
}
116+
```
117+
118+
For a localhost configuration, you can omit `HOST` or specify
119+
`"HOST": "localhost"`.
120+
121+
`HOST` only needs a scheme prefix for SRV connections (`mongodb+srv://`). A
122+
`mongodb://` prefix is never required.
123+
124+
`OPTIONS` is an optional dictionary of parameters that will be passed to
125+
[`MongoClient`](https://pymongo.readthedocs.io/en/stable/api/pymongo/mongo_client.html).
126+
127+
`USER`, `PASSWORD`, and `PORT` (if 27017) may also be optional.
128+
129+
For a replica set or sharded cluster where you have multiple hosts, include
130+
all of them in `HOST`, e.g.
131+
`"mongodb://mongos0.example.com:27017,mongos1.example.com:27017"`.
132+
133+
Alternatively, if you prefer to simply paste in a MongoDB URI rather than parse
134+
it into the format above, you can use:
135+
136+
```python
137+
import django_mongodb_backend
138+
139+
MONGODB_URI = "mongodb+srv://my_user:[email protected]/myDatabase?retryWrites=true&w=majority&tls=false"
140+
DATABASES["default"] = django_mongodb_backend.parse_uri(MONGODB_URI)
141+
```
142+
143+
This constructs a `DATABASES` setting equivalent to the first example.
144+
145+
#### `django_mongodb_backend.parse_uri(uri, conn_max_age=0, test=None)`
146+
147+
`parse_uri()` provides a few options to customize the resulting `DATABASES`
148+
setting, but for maximum flexibility, construct `DATABASES` manually as
149+
described above.
150+
151+
- Use `conn_max_age` to configure [persistent database connections](
152+
https://docs.djangoproject.com/en/stable/ref/databases/#persistent-database-connections).
153+
- Use `test` to provide a dictionary of [settings for test databases](
154+
https://docs.djangoproject.com/en/stable/ref/settings/#test).
155+
156+
Congratulations, your project is ready to go!
157+
158+
## Notes on Django QuerySets
159+
160+
* `QuerySet.explain()` supports the [`comment` and `verbosity` options](
161+
https://www.mongodb.com/docs/manual/reference/command/explain/#command-fields).
162+
163+
Example: `QuerySet.explain(comment="...", verbosity="...")`
164+
165+
Valid values for `verbosity` are `"queryPlanner"` (default),
166+
`"executionStats"`, and `"allPlansExecution"`.
167+
168+
## Known issues and limitations
169+
170+
- The following `QuerySet` methods aren't supported:
171+
- `bulk_update()`
172+
- `dates()`
173+
- `datetimes()`
174+
- `distinct()`
175+
- `extra()`
176+
- `prefetch_related()`
177+
178+
- `QuerySet.delete()` and `update()` do not support queries that span multiple
179+
collections.
180+
181+
- `DateTimeField` doesn't support microsecond precision, and correspondingly,
182+
`DurationField` stores milliseconds rather than microseconds.
183+
184+
- The following database functions aren't supported:
185+
- `Chr`
186+
- `ExtractQuarter`
187+
- `MD5`
188+
- `Now`
189+
- `Ord`
190+
- `Pad`
191+
- `Repeat`
192+
- `Reverse`
193+
- `Right`
194+
- `SHA1`, `SHA224`, `SHA256`, `SHA384`, `SHA512`
195+
- `Sign`
196+
197+
- The `tzinfo` parameter of the `Trunc` database functions doesn't work
198+
properly because MongoDB converts the result back to UTC.
199+
200+
- When querying `JSONField`:
201+
- There is no way to distinguish between a JSON "null" (represented by
202+
`Value(None, JSONField())`) and a SQL null (queried using the `isnull`
203+
lookup). Both of these queries return both of these nulls.
204+
- Some queries with `Q` objects, e.g. `Q(value__foo="bar")`, don't work
205+
properly, particularly with `QuerySet.exclude()`.
206+
- Filtering for a `None` key, e.g. `QuerySet.filter(value__j=None)`
207+
incorrectly returns objects where the key doesn't exist.
208+
- You can study the skipped tests in `DatabaseFeatures.django_test_skips` for
209+
more details on known issues.
210+
211+
- Due to the lack of ability to introspect MongoDB collection schema,
212+
`migrate --fake-initial` isn't supported.
213+
214+
215+
### Debug logging
216+
217+
To troubleshoot MongoDB connectivity issues, you can enable [PyMongo's logging](
218+
https://pymongo.readthedocs.io/en/stable/examples/logging.html) using
219+
[Django's `LOGGING` setting](https://docs.djangoproject.com/en/stable/topics/logging/).
220+
221+
This is a minimal `LOGGING` setting that enables PyMongo's `DEBUG` logging:
222+
223+
```python
224+
LOGGING = {
225+
"version": 1,
226+
"disable_existing_loggers": False,
227+
"handlers": {
228+
"console": {
229+
"class": "logging.StreamHandler",
230+
},
231+
},
232+
"loggers": {
233+
"pymongo": {
234+
"handlers": ["console"],
235+
"level": "DEBUG",
236+
},
237+
},
238+
}
239+
```

0 commit comments

Comments
 (0)