Skip to content

Commit

Permalink
edits
Browse files Browse the repository at this point in the history
  • Loading branch information
timgraham committed Dec 4, 2024
1 parent 6e636cd commit 33b5481
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 51 deletions.
25 changes: 7 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,8 @@ DATABASES = {
`OPTIONS` is an optional dictionary of parameters that will be passed to
[`MongoClient`](https://pymongo.readthedocs.io/en/stable/api/pymongo/mongo_client.html).

Alternatively, those that follow the [twelve-factor app](
https://www.12factor.net/backing-services) methodology can configure Django's
`DATABASES` with `django_mongodb.parse_uri(MONGODB_URI)`:
Alternatively, if you prefer to simply paste in a MongoDB URI rather than
parsing it into the format above, you can use:

```python
import django_mongodb
Expand All @@ -132,22 +131,12 @@ MONGODB_URI = "mongodb+srv://myDatabaseUser:D1fficultP%[email protected]
DATABASES["default"] = django_mongodb.parse_uri(MONGODB_URI)
```

#### Additional `parse_uri` options
#### `django_mongodb.parse_uri(uri, conn_max_age=0, conn_health_checks=False, test=None)`

The `parse_uri` function accepts these keyword arguments:

| Keyword argument | Default setting |
| -------------------- | --------------------- |
| `conn_max_age` | `0` |
| `conn_health_checks` | `False` |
| `test` | `None` |

- The `conn_max_age` and `conn_health_checks` options can be used with
[persistent database connections](
https://docs.djangoproject.com/en/latest/ref/databases/#persistent-database-connections).

- The `test` option can be used to provide a dictionary of [settings for test databases](
https://docs.djangoproject.com/en/latest/ref/settings/#test).
- Use `conn_max_age` and `conn_health_checks` to configure [persistent database
connections](https://docs.djangoproject.com/en/stable/ref/databases/#persistent-database-connections).
- Use `test` to provide a dictionary of [settings for test databases](
https://docs.djangoproject.com/en/stable/ref/settings/#test).

Congratulations, your project is ready to go!

Expand Down
11 changes: 2 additions & 9 deletions django_mongodb/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,12 @@ def check_django_compatability():

def parse_uri(uri, conn_max_age=0, conn_health_checks=False, test=None):
"""
Parse a MongoDB URI and return a dictionary of Django database
settings. This function is a wrapper around PyMongo's
``pymongo.uri_parser.parse_uri()`` function that converts PyMongo's
settings dictionary into a Django database settings dictionary.
Convert the given uri into a dictionary suitable for Django's DATABASES
setting.
"""
uri = parse_uri_mongo(uri)

host = None
port = None

if uri["fqdn"] is not None:
# If the fqdn is present, this is a SRV URI and the host is the fqdn.
host = f"mongodb+srv://{uri['fqdn']}"
Expand All @@ -47,7 +43,6 @@ def parse_uri(uri, conn_max_age=0, conn_health_checks=False, test=None):
host, port = nodelist[0]
elif len(nodelist) > 1:
host = ",".join([f"{host}:{port}" for host, port in nodelist])

settings_dict = {
"ENGINE": "django_mongodb",
"NAME": uri["database"],
Expand All @@ -59,10 +54,8 @@ def parse_uri(uri, conn_max_age=0, conn_health_checks=False, test=None):
"CONN_MAX_AGE": conn_max_age,
"CONN_HEALTH_CHECKS": conn_health_checks,
}

if test:
settings_dict["TEST"] = test

return settings_dict


Expand Down
49 changes: 25 additions & 24 deletions tests/utils_/test_parse.py → tests/utils_/test_parse_uri.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,12 @@
import pymongo
from django.test import SimpleTestCase

import django_mongodb
from django_mongodb import parse_uri

URI = "mongodb+srv://myDatabaseUser:D1fficultP%[email protected]/myDatabase?retryWrites=true&w=majority&tls=false"


class MongoParseURITests(SimpleTestCase):
"""
Test django_mongodb.parse_uri(uri) function
"""

class ParseURITests(SimpleTestCase):
def setUp(self):
self.srv_record = MagicMock()
self.srv_record.target.to_text.return_value = "cluster0.example.mongodb.net"
Expand All @@ -21,53 +17,58 @@ def setUp(self):
self.addCleanup(self.patcher.stop)

@patch("dns.resolver.resolve")
def test_uri(self, mock_resolver):
settings_dict = django_mongodb.parse_uri(
"mongodb://cluster0.example.mongodb.net/myDatabase"
)
def test_simple_uri(self, mock_resolver):
settings_dict = parse_uri("mongodb://cluster0.example.mongodb.net/myDatabase")
self.assertEqual(settings_dict["ENGINE"], "django_mongodb")
self.assertEqual(settings_dict["NAME"], "myDatabase")
self.assertEqual(settings_dict["HOST"], "cluster0.example.mongodb.net")

@patch("dns.resolver.resolve")
def test_no_database(self, mock_resolver):
settings_dict = parse_uri("mongodb://cluster0.example.mongodb.net/")
self.assertEqual(settings_dict["ENGINE"], "django_mongodb")
self.assertIsNone(settings_dict["NAME"])
self.assertEqual(settings_dict["HOST"], "cluster0.example.mongodb.net")

@patch("dns.resolver.resolve")
def test_srv_uri_with_options(self, mock_resolver):
settings_dict = django_mongodb.parse_uri(URI)
settings_dict = parse_uri(URI)
self.assertEqual(settings_dict["ENGINE"], "django_mongodb")
self.assertEqual(settings_dict["NAME"], "myDatabase")
self.assertEqual(settings_dict["HOST"], "mongodb+srv://cluster0.example.mongodb.net")
self.assertEqual(settings_dict["USER"], "myDatabaseUser")
self.assertEqual(settings_dict["PASSWORD"], "D1fficultP@ssw0rd")
self.assertEqual(settings_dict["PORT"], None)
self.assertIsNone(settings_dict["PORT"])
self.assertEqual(
settings_dict["OPTIONS"], {"retryWrites": True, "w": "majority", "tls": False}
)

def test_localhost(self):
settings_dict = django_mongodb.parse_uri("mongodb://localhost/myDatabase")
settings_dict = parse_uri("mongodb://localhost/myDatabase")
self.assertEqual(settings_dict["ENGINE"], "django_mongodb")
self.assertEqual(settings_dict["NAME"], "myDatabase")
self.assertEqual(settings_dict["HOST"], "localhost")

def test_localhost_bad_credentials(self):
with self.assertRaises(pymongo.errors.InvalidURI):
django_mongodb.parse_uri("mongodb://:@localhost/myDatabase")

@patch("dns.resolver.resolve")
def test_conn_max_age_kwarg(self, mock_resolver):
settings_dict = django_mongodb.parse_uri(URI, conn_max_age=600)
def test_conn_max_age(self, mock_resolver):
settings_dict = parse_uri(URI, conn_max_age=600)
self.assertEqual(settings_dict["CONN_MAX_AGE"], 600)

@patch("dns.resolver.resolve")
def test_conn_health_checks_kwarg(self, mock_resolver):
settings_dict = django_mongodb.parse_uri(URI, conn_health_checks=True)
def test_conn_health_checks(self, mock_resolver):
settings_dict = parse_uri(URI, conn_health_checks=True)
self.assertEqual(settings_dict["CONN_HEALTH_CHECKS"], True)

@patch("dns.resolver.resolve")
def test_test_kwarg(self, mock_resolver):
settings_dict = django_mongodb.parse_uri(URI, test={"NAME": "test_db"})
settings_dict = parse_uri(URI, test={"NAME": "test_db"})
self.assertEqual(settings_dict["TEST"]["NAME"], "test_db")

def test_invalid_credentials(self):
with self.assertRaises(pymongo.errors.InvalidURI):
parse_uri("mongodb://:@localhost/myDatabase")

@patch("dns.resolver.resolve")
def test_uri_no_prefix(self, mock_resolver):
def test_no_prefix(self, mock_resolver):
with self.assertRaises(pymongo.errors.InvalidURI):
django_mongodb.parse_uri("cluster0.example.mongodb.net/myDatabase")
parse_uri("cluster0.example.mongodb.net/myDatabase")

0 comments on commit 33b5481

Please sign in to comment.