Skip to content

Commit ea9ef5f

Browse files
committed
Merge pull request #6 from elasticsales/feature-lower-fields
LowerStringField and LowerEmailField
2 parents fc897ca + 3c8f7da commit ea9ef5f

File tree

4 files changed

+81
-6
lines changed

4 files changed

+81
-6
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
*.pyc
2+
venv/

fields/fields.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from datetime import timedelta
22
from mongoengine.base import BaseField
3+
from mongoengine.fields import StringField, EmailField
34

45
import os
56
import datetime
@@ -18,7 +19,7 @@ class TimedeltaField(BaseField):
1819
1920
Looks to the outside world like a datatime.timedelta, but stores
2021
in the database as an integer (or float) number of seconds.
21-
22+
2223
"""
2324
def validate(self, value):
2425
if not isinstance(value, (timedelta, int, float)):
@@ -53,11 +54,11 @@ def total_seconds(value):
5354

5455

5556
class LocalStorageFileField(BaseField):
56-
57+
5758
proxy_class = FieldFile
5859

5960
def __init__(self,
60-
db_alias=DEFAULT_CONNECTION_NAME,
61+
db_alias=DEFAULT_CONNECTION_NAME,
6162
name=None,
6263
upload_to='',
6364
storage=None,
@@ -93,7 +94,7 @@ def __get__(self, instance, owner):
9394
file.instance = instance
9495
file.field = self
9596
file.storage = self.storage
96-
97+
9798
return instance._data[self.name]
9899

99100

@@ -122,11 +123,33 @@ def to_mongo(self, value):
122123
value.save(value.name, value)
123124
return value.path
124125

125-
return value.name
126+
return value.name
126127

127128

128129
def to_python(self, value):
129130
eu = self
130131
return eu.proxy_class(eu.owner_document, eu, value)
131132

132133

134+
class LowerStringField(StringField):
135+
def __set__(self, instance, value):
136+
value = self.to_python(value)
137+
return super(LowerStringField, self).__set__(instance, value)
138+
139+
def to_python(self, value):
140+
if value:
141+
value = value.lower()
142+
return value
143+
144+
def prepare_query_value(self, op, value):
145+
value = value.lower() if value else value
146+
return super(LowerStringField, self).prepare_query_value(op, value)
147+
148+
149+
class LowerEmailField(LowerStringField):
150+
151+
def validate(self, value):
152+
if not EmailField.EMAIL_REGEX.match(value):
153+
self.error('Invalid Mail-address: %s' % value)
154+
super(LowerEmailField, self).validate(value)
155+

fields/test_fields.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import unittest2 as unittest
22
from datetime import timedelta
3-
from fields import TimedeltaField
3+
from mongoengine import Document, NotUniqueError, ValidationError, connect
4+
from mongoengine.connection import get_db
5+
6+
from django.conf import settings
7+
settings.configure(
8+
USE_TZ=True,
9+
INSTALLED_APPS=[]
10+
)
11+
12+
from fields import TimedeltaField, LowerStringField, LowerEmailField
13+
414

515
class OldStyleTimedelta(timedelta):
616
"Used for backwards compatibility testing"
@@ -22,5 +32,43 @@ def test_total_seconds_26(self):
2232
value = OldStyleTimedelta(minutes=1, seconds=10)
2333
self.assertEqual(self.field.total_seconds(value), 70)
2434

35+
class LowerStringFieldTestCase(unittest.TestCase):
36+
37+
def setUp(self):
38+
connect(db='extrasmongoenginetest')
39+
self.db = get_db()
40+
41+
def tearDown(self):
42+
for collection in self.db.collection_names():
43+
if 'system.' in collection:
44+
continue
45+
self.db.drop_collection(collection)
46+
47+
def test_case_insensitive_querying(self):
48+
class BlogPost(Document):
49+
slug = LowerStringField()
50+
51+
BlogPost.objects.create(slug='whatever')
52+
self.assertEqual(BlogPost.objects.get(slug='WHATEVER').slug, 'whatever')
53+
54+
def test_case_insensitive_uniqueness(self):
55+
class User(Document):
56+
username = LowerStringField(unique=True)
57+
58+
User.objects.create(username='whatever')
59+
dupe = User(username='WHATEVER')
60+
self.assertRaises(NotUniqueError, dupe.save)
61+
62+
def test_lower_email_validation(self):
63+
class User(Document):
64+
email = LowerEmailField()
65+
66+
u = User.objects.create(email='[email protected]')
67+
self.assertEqual(User.objects.get(email='[email protected]'), u)
68+
69+
u2 = User(email='whatever')
70+
self.assertRaises(ValidationError, u2.save)
71+
72+
2573
if __name__ == '__main__':
2674
unittest.main()

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
unittest2
2+
django
3+
mongoengine

0 commit comments

Comments
 (0)