Skip to content

Commit 6240b1f

Browse files
committed
INTPYTHON-509 Add db_name parameter to parse_uri()
1 parent 6ba78c3 commit 6240b1f

File tree

5 files changed

+58
-28
lines changed

5 files changed

+58
-28
lines changed

.github/workflows/mongodb_settings.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from django_mongodb_backend import parse_uri
44

55
if mongodb_uri := os.getenv("MONGODB_URI"):
6-
db_settings = parse_uri(mongodb_uri)
6+
db_settings = parse_uri(mongodb_uri, db_name="dummy")
77

88
# Workaround for https://github.com/mongodb-labs/mongo-orchestration/issues/268
99
if db_settings["USER"] and db_settings["PASSWORD"]:

README.md

+5-12
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,17 @@ $ django-admin startproject example --template https://github.com/mongodb-labs/d
4646

4747
### Connect to the database
4848

49-
Navigate to your `example/settings.py` file and find the variable named
50-
`DATABASES` Replace the `DATABASES` variable with this:
49+
Navigate to your `example/settings.py` file and replace the `DATABASES`
50+
setting like so:
5151

5252
```python
5353
DATABASES = {
54-
"default": django_mongodb_backend.parse_uri("<CONNECTION_STRING_URI>"),
54+
"default": django_mongodb_backend.parse_uri(
55+
"<CONNECTION_STRING_URI>", db_name="example"
56+
),
5557
}
5658
```
5759

58-
The MongoDB `<CONNECTION_STRING_URI>` must also specify a database for the
59-
`parse_uri` function to work.
60-
If not already included, make sure you provide a value for `<DATABASE_NAME>`
61-
in your URI as shown in the example below:
62-
```bash
63-
mongodb+srv://myDatabaseUser:D1fficultP%[email protected]/<DATABASE_NAME>?retryWrites=true&w=majority
64-
```
65-
66-
6760
### Run the server
6861
To verify that you installed Django MongoDB Backend and correctly configured your project, run the following command from your project root:
6962
```bash

django_mongodb_backend/utils.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def check_django_compatability():
2828
)
2929

3030

31-
def parse_uri(uri, conn_max_age=0, test=None):
31+
def parse_uri(uri, *, db_name=None, conn_max_age=0, test=None):
3232
"""
3333
Convert the given uri into a dictionary suitable for Django's DATABASES
3434
setting.
@@ -45,16 +45,21 @@ def parse_uri(uri, conn_max_age=0, test=None):
4545
host, port = nodelist[0]
4646
elif len(nodelist) > 1:
4747
host = ",".join([f"{host}:{port}" for host, port in nodelist])
48+
db_name = db_name or uri["database"]
49+
if not db_name:
50+
raise ImproperlyConfigured("You must provide the db_name parameter.")
4851
settings_dict = {
4952
"ENGINE": "django_mongodb_backend",
50-
"NAME": uri["database"],
53+
"NAME": db_name,
5154
"HOST": host,
5255
"PORT": port,
5356
"USER": uri.get("username"),
5457
"PASSWORD": uri.get("password"),
5558
"OPTIONS": uri.get("options"),
5659
"CONN_MAX_AGE": conn_max_age,
5760
}
61+
if "authSource" not in settings_dict["OPTIONS"] and uri["database"]:
62+
settings_dict["OPTIONS"]["authSource"] = uri["database"]
5863
if test:
5964
settings_dict["TEST"] = test
6065
return settings_dict

docs/source/ref/utils.rst

+6-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ following parts can be considered stable.
1212
``parse_uri()``
1313
===============
1414

15-
.. function:: parse_uri(uri, conn_max_age=0, test=None)
15+
.. function:: parse_uri(uri, db_name=None, conn_max_age=0, test=None)
1616

1717
Parses a MongoDB `connection string`_ into a dictionary suitable for Django's
1818
:setting:`DATABASES` setting.
@@ -23,8 +23,11 @@ Example::
2323

2424
import django_mongodb_backend
2525

26-
MONGODB_URI = "mongodb+srv://my_user:[email protected]/myDatabase?retryWrites=true&w=majority&tls=false"
27-
DATABASES["default"] = django_mongodb_backend.parse_uri(MONGODB_URI)
26+
MONGODB_URI = "mongodb+srv://my_user:[email protected]/defaultauthdb?retryWrites=true&w=majority&tls=false"
27+
DATABASES["default"] = django_mongodb_backend.parse_uri(MONGODB_URI, db_name="example")
28+
29+
You must specify ``db_name`` (the :setting:`NAME` of your database) if the URI
30+
doesn't specify ``defaultauthdb``.
2831

2932
You can use the parameters to customize the resulting :setting:`DATABASES`
3033
setting:

tests/backend_/utils/test_parse_uri.py

+39-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from unittest.mock import patch
22

33
import pymongo
4+
from django.core.exceptions import ImproperlyConfigured
45
from django.test import SimpleTestCase
56

67
from django_mongodb_backend import parse_uri
@@ -12,11 +13,28 @@ def test_simple_uri(self):
1213
self.assertEqual(settings_dict["ENGINE"], "django_mongodb_backend")
1314
self.assertEqual(settings_dict["NAME"], "myDatabase")
1415
self.assertEqual(settings_dict["HOST"], "cluster0.example.mongodb.net")
16+
self.assertEqual(settings_dict["OPTIONS"], {"authSource": "myDatabase"})
1517

16-
def test_no_database(self):
17-
settings_dict = parse_uri("mongodb://cluster0.example.mongodb.net")
18-
self.assertIsNone(settings_dict["NAME"])
18+
def test_db_name(self):
19+
settings_dict = parse_uri("mongodb://cluster0.example.mongodb.net/", db_name="myDatabase")
20+
self.assertEqual(settings_dict["ENGINE"], "django_mongodb_backend")
21+
self.assertEqual(settings_dict["NAME"], "myDatabase")
22+
self.assertEqual(settings_dict["HOST"], "cluster0.example.mongodb.net")
23+
self.assertEqual(settings_dict["OPTIONS"], {})
24+
25+
def test_db_name_overrides_default_auth_db(self):
26+
settings_dict = parse_uri(
27+
"mongodb://cluster0.example.mongodb.net/default_auth_db", db_name="myDatabase"
28+
)
29+
self.assertEqual(settings_dict["ENGINE"], "django_mongodb_backend")
30+
self.assertEqual(settings_dict["NAME"], "myDatabase")
1931
self.assertEqual(settings_dict["HOST"], "cluster0.example.mongodb.net")
32+
self.assertEqual(settings_dict["OPTIONS"], {"authSource": "default_auth_db"})
33+
34+
def test_no_database(self):
35+
msg = "You must provide the db_name parameter."
36+
with self.assertRaisesMessage(ImproperlyConfigured, msg):
37+
parse_uri("mongodb://cluster0.example.mongodb.net")
2038

2139
def test_srv_uri_with_options(self):
2240
uri = "mongodb+srv://my_user:[email protected]/my_database?retryWrites=true&w=majority"
@@ -30,35 +48,46 @@ def test_srv_uri_with_options(self):
3048
self.assertEqual(settings_dict["PASSWORD"], "my_password")
3149
self.assertIsNone(settings_dict["PORT"])
3250
self.assertEqual(
33-
settings_dict["OPTIONS"], {"retryWrites": True, "w": "majority", "tls": True}
51+
settings_dict["OPTIONS"],
52+
{"authSource": "my_database", "retryWrites": True, "w": "majority", "tls": True},
3453
)
3554

3655
def test_localhost(self):
37-
settings_dict = parse_uri("mongodb://localhost")
56+
settings_dict = parse_uri("mongodb://localhost/db")
3857
self.assertEqual(settings_dict["HOST"], "localhost")
3958
self.assertEqual(settings_dict["PORT"], 27017)
4059

4160
def test_localhost_with_port(self):
42-
settings_dict = parse_uri("mongodb://localhost:27018")
61+
settings_dict = parse_uri("mongodb://localhost:27018/db")
4362
self.assertEqual(settings_dict["HOST"], "localhost")
4463
self.assertEqual(settings_dict["PORT"], 27018)
4564

4665
def test_hosts_with_ports(self):
47-
settings_dict = parse_uri("mongodb://localhost:27017,localhost:27018")
66+
settings_dict = parse_uri("mongodb://localhost:27017,localhost:27018/db")
4867
self.assertEqual(settings_dict["HOST"], "localhost:27017,localhost:27018")
4968
self.assertEqual(settings_dict["PORT"], None)
5069

5170
def test_hosts_without_ports(self):
52-
settings_dict = parse_uri("mongodb://host1.net,host2.net")
71+
settings_dict = parse_uri("mongodb://host1.net,host2.net/db")
5372
self.assertEqual(settings_dict["HOST"], "host1.net:27017,host2.net:27017")
5473
self.assertEqual(settings_dict["PORT"], None)
5574

75+
def test_auth_source_in_query_string(self):
76+
settings_dict = parse_uri("mongodb://localhost/?authSource=auth", db_name="db")
77+
self.assertEqual(settings_dict["NAME"], "db")
78+
self.assertEqual(settings_dict["OPTIONS"], {"authSource": "auth"})
79+
80+
def test_auth_source_in_query_string_overrides_defaultauthdb(self):
81+
settings_dict = parse_uri("mongodb://localhost/db?authSource=auth")
82+
self.assertEqual(settings_dict["NAME"], "db")
83+
self.assertEqual(settings_dict["OPTIONS"], {"authSource": "auth"})
84+
5685
def test_conn_max_age(self):
57-
settings_dict = parse_uri("mongodb://localhost", conn_max_age=600)
86+
settings_dict = parse_uri("mongodb://localhost/db", conn_max_age=600)
5887
self.assertEqual(settings_dict["CONN_MAX_AGE"], 600)
5988

6089
def test_test_kwarg(self):
61-
settings_dict = parse_uri("mongodb://localhost", test={"NAME": "test_db"})
90+
settings_dict = parse_uri("mongodb://localhost/db", test={"NAME": "test_db"})
6291
self.assertEqual(settings_dict["TEST"], {"NAME": "test_db"})
6392

6493
def test_invalid_credentials(self):

0 commit comments

Comments
 (0)