Skip to content

Commit 1df75fc

Browse files
WaVEVtimgraham
andcommitted
add ObjectIdField
Co-authored-by: Tim Graham <[email protected]>
1 parent f218620 commit 1df75fc

File tree

15 files changed

+445
-13
lines changed

15 files changed

+445
-13
lines changed

.github/workflows/runtests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"force_insert_update",
5858
"foreign_object",
5959
"forms_tests",
60+
"forms_tests_",
6061
"from_db_value",
6162
"generic_inline_admin",
6263
"generic_relations",

django_mongodb/fields/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from .auto import ObjectIdAutoField
22
from .duration import register_duration_field
33
from .json import register_json_field
4+
from .objectid import ObjectIdField
45

5-
__all__ = ["register_fields", "ObjectIdAutoField"]
6+
__all__ = ["register_fields", "ObjectIdAutoField", "ObjectIdField"]
67

78

89
def register_fields():

django_mongodb/fields/auto.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22
from django.core import exceptions
33
from django.db.models.fields import AutoField
44
from django.utils.functional import cached_property
5-
from django.utils.translation import gettext_lazy as _
65

6+
from .objectid import ObjectIdMixin
77

8-
class ObjectIdAutoField(AutoField):
9-
default_error_messages = {
10-
"invalid": _("“%(value)s” value must be an Object Id."),
11-
}
12-
description = _("Object Id")
138

9+
class ObjectIdAutoField(ObjectIdMixin, AutoField):
1410
def __init__(self, *args, **kwargs):
1511
kwargs["db_column"] = "_id"
1612
super().__init__(*args, **kwargs)
@@ -42,12 +38,6 @@ def get_prep_value(self, value):
4238
def get_internal_type(self):
4339
return "ObjectIdAutoField"
4440

45-
def db_type(self, connection):
46-
return "objectId"
47-
48-
def rel_db_type(self, connection):
49-
return "objectId"
50-
5141
def to_python(self, value):
5242
if value is None or isinstance(value, int):
5343
return value

django_mongodb/fields/objectid.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from bson import ObjectId, errors
2+
from django.core import exceptions
3+
from django.db.models.fields import Field
4+
from django.utils.translation import gettext_lazy as _
5+
6+
from django_mongodb import forms
7+
8+
9+
class ObjectIdMixin:
10+
default_error_messages = {
11+
"invalid": _("“%(value)s” is not a valid Object Id."),
12+
}
13+
description = _("Object Id")
14+
15+
def db_type(self, connection):
16+
return "objectId"
17+
18+
def rel_db_type(self, connection):
19+
return "objectId"
20+
21+
def get_prep_value(self, value):
22+
value = super().get_prep_value(value)
23+
return self.to_python(value)
24+
25+
def to_python(self, value):
26+
if value is None:
27+
return value
28+
try:
29+
return ObjectId(value)
30+
except (errors.InvalidId, TypeError):
31+
raise exceptions.ValidationError(
32+
self.error_messages["invalid"],
33+
code="invalid",
34+
params={"value": value},
35+
) from None
36+
37+
def formfield(self, **kwargs):
38+
return super().formfield(
39+
**{
40+
"form_class": forms.ObjectIdField,
41+
**kwargs,
42+
}
43+
)
44+
45+
46+
class ObjectIdField(ObjectIdMixin, Field):
47+
def deconstruct(self):
48+
name, path, args, kwargs = super().deconstruct()
49+
if path.startswith("django_mongodb.fields.objectid"):
50+
path = path.replace("django_mongodb.fields.objectid", "django_mongodb.fields")
51+
return name, path, args, kwargs
52+
53+
def get_internal_type(self):
54+
return "ObjectIdField"

django_mongodb/forms/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .fields import ObjectIdField
2+
3+
__all__ = ["ObjectIdField"]

django_mongodb/forms/fields.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from bson import ObjectId
2+
from bson.errors import InvalidId
3+
from django.core.exceptions import ValidationError
4+
from django.forms import Field
5+
from django.utils.translation import gettext_lazy as _
6+
7+
8+
class ObjectIdField(Field):
9+
default_error_messages = {
10+
"invalid": _("Enter a valid Object Id."),
11+
}
12+
13+
def prepare_value(self, value):
14+
if isinstance(value, ObjectId):
15+
return str(value)
16+
return value
17+
18+
def to_python(self, value):
19+
value = super().to_python(value)
20+
if value in self.empty_values:
21+
return None
22+
if not isinstance(value, ObjectId):
23+
try:
24+
value = ObjectId(value)
25+
except InvalidId:
26+
raise ValidationError(self.error_messages["invalid"], code="invalid") from None
27+
return value

docs/source/fields.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Model field reference
2+
=====================
3+
4+
.. module:: django_mongodb.fields
5+
6+
Some MongoDB-specific fields are available in ``django_mongodb.fields``.
7+
8+
``ObjectIdField``
9+
-----------------
10+
11+
.. class:: ObjectIdField
12+
13+
Stores an :class:`~bson.objectid.ObjectId`.

docs/source/forms.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Forms API reference
2+
===================
3+
4+
.. module:: django_mongodb.forms
5+
6+
Some MongoDB-specific fields are available in ``django_mongodb.forms``.
7+
8+
``ObjectIdField``
9+
-----------------
10+
11+
.. class:: ObjectIdField
12+
13+
Stores an :class:`~bson.objectid.ObjectId`.

docs/source/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ django-mongodb 5.0.x documentation
55
:maxdepth: 1
66
:caption: Contents:
77

8+
fields
89
querysets
10+
forms
911

1012
Indices and tables
1113
==================

tests/forms_tests_/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)