Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for django >= '1.8' version and compatibility with django versions earlier #89

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion mongodbforms/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@
from django.forms.widgets import media_property
from django.core.exceptions import FieldError
from django.core.validators import EMPTY_VALUES
from django.forms.util import ErrorList

if (django.get_version() < '1.8'):
# Compatibility with django earlier version
from django.forms.util import ErrorList
else:
# Compatibility with django newest version
from django.forms.utils import ErrorList

from django.forms.formsets import BaseFormSet, formset_factory
from django.utils.translation import ugettext_lazy as _, ugettext
from django.utils.text import capfirst, get_valid_filename
Expand Down
36 changes: 20 additions & 16 deletions mongodbforms/fieldgenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
try:
from django.utils.encoding import smart_unicode
except ImportError:
from django.forms.util import smart_unicode
if (django.get_version() < '1.8'):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably just use something like above with try ... except ImportError.

from django.forms.util import smart_unicode
else:
from django.forms.utils import smart_unicode

from django.utils.text import capfirst

from mongoengine import (ReferenceField as MongoReferenceField,
Expand All @@ -34,14 +38,14 @@

class MongoFormFieldGenerator(object):
"""This class generates Django form-fields for mongoengine-fields."""

# used for fields that fit in one of the generate functions
# but don't actually have the name.
generator_map = {
'sortedlistfield': 'generate_listfield',
'longfield': 'generate_intfield',
}

form_field_map = {
'stringfield': MongoCharField,
'stringfield_choices': forms.TypedChoiceField,
Expand All @@ -63,12 +67,12 @@ class MongoFormFieldGenerator(object):
'filefield': forms.FileField,
'imagefield': forms.ImageField,
}

# uses the same keys as form_field_map
widget_override_map = {
'stringfield_long': forms.Textarea,
}

def __init__(self, field_overrides={}, widget_overrides={}):
self.form_field_map.update(field_overrides)
self.widget_override_map.update(widget_overrides)
Expand All @@ -83,22 +87,22 @@ def generate(self, field, **kwargs):
# to handle then a simple field
if isinstance(field, MongoEmbeddedDocumentField):
return

attr_name = 'generate_%s' % field.__class__.__name__.lower()
if hasattr(self, attr_name):
return getattr(self, attr_name)(field, **kwargs)

for cls in field.__class__.__bases__:
cls_name = cls.__name__.lower()

attr_name = 'generate_%s' % cls_name
if hasattr(self, attr_name):
return getattr(self, attr_name)(field, **kwargs)

if cls_name in self.form_field_map:
attr = self.generator_map.get(cls_name)
return getattr(self, attr)(field, **kwargs)

raise NotImplementedError('%s is not supported by MongoForm' %
field.__class__.__name__)

Expand Down Expand Up @@ -134,7 +138,7 @@ def get_field_help_text(self, field):
return field.help_text
else:
return ''

def get_field_default(self, field):
if isinstance(field, (MongoListField, MongoMapField)):
f = field.field
Expand All @@ -148,7 +152,7 @@ def get_field_default(self, field):
else:
d['initial'] = field.default
return f.default

def check_widget(self, map_key):
if map_key in self.widget_override_map:
return {'widget': self.widget_override_map.get(map_key)}
Expand Down Expand Up @@ -181,7 +185,7 @@ def generate_stringfield(self, field, **kwargs):
})
if field.regex:
defaults['validators'] = [RegexValidator(regex=field.regex)]

form_class = self.form_field_map.get(map_key)
defaults.update(self.check_widget(map_key))
defaults.update(kwargs)
Expand Down Expand Up @@ -324,7 +328,7 @@ def generate_listfield(self, field, **kwargs):
# So we just ignore them
if isinstance(field.field, MongoEmbeddedDocumentField):
return

defaults = {
'label': self.get_field_label(field),
'help_text': self.get_field_help_text(field),
Expand All @@ -351,13 +355,13 @@ def generate_listfield(self, field, **kwargs):
defaults.update(self.check_widget(map_key))
defaults.update(kwargs)
return form_class(**defaults)

def generate_mapfield(self, field, **kwargs):
# We can't really handle embedded documents here.
# So we just ignore them
if isinstance(field.field, MongoEmbeddedDocumentField):
return

map_key = 'mapfield'
form_field = self.generate(field.field)
defaults = {
Expand Down Expand Up @@ -433,10 +437,10 @@ def check_widget(self, map_key):
override = super(Html5FormFieldGenerator, self).check_widget(map_key)
if override != {}:
return override

chunks = map_key.split('field')
kind = chunks[0]

if kind == 'email':
if hasattr(forms, 'EmailInput'):
return {'widget': forms.EmailInput}
Expand Down
80 changes: 43 additions & 37 deletions mongodbforms/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,30 @@
from django.utils.encoding import force_text as force_unicode
except ImportError:
from django.utils.encoding import force_unicode

try:
from django.utils.encoding import smart_text as smart_unicode
except ImportError:
try:
from django.utils.encoding import smart_unicode
except ImportError:
from django.forms.util import smart_unicode

if (django.get_version() < '1.8'):
from django.forms.util import smart_unicode
else:
from django.forms.utils import smart_unicode

from django.utils.translation import ugettext_lazy as _
from django.forms.util import ErrorList
if (django.get_version() < '1.8'):
from django.forms.util import ErrorList
else:
from django.forms.utils import ErrorList
from django.core.exceptions import ValidationError

try: # objectid was moved into bson in pymongo 1.9
from bson.errors import InvalidId
except ImportError:
from pymongo.errors import InvalidId

from mongodbforms.widgets import ListWidget, MapWidget, HiddenMapWidget


Expand Down Expand Up @@ -66,23 +72,23 @@ def to_python(self, value):
if value in EMPTY_VALUES:
return None
return value


class MongoCharField(NormalizeValueMixin, forms.CharField):
pass


class MongoEmailField(NormalizeValueMixin, forms.EmailField):
pass


class MongoSlugField(NormalizeValueMixin, forms.SlugField):
pass


class MongoURLField(NormalizeValueMixin, forms.URLField):
pass


class ReferenceField(forms.ChoiceField):
"""
Expand All @@ -96,7 +102,7 @@ def __init__(self, queryset, empty_label="---------", *args, **kwargs):

def _get_queryset(self):
return self._queryset.clone()

def _set_queryset(self, queryset):
self._queryset = queryset
self.widget.choices = self.choices
Expand Down Expand Up @@ -130,15 +136,15 @@ def clean(self, value):
return None

oid = super(ReferenceField, self).clean(value)

try:
obj = self.queryset.get(pk=oid)
except (TypeError, InvalidId, self.queryset._document.DoesNotExist):
raise forms.ValidationError(
self.error_messages['invalid_choice'] % {'value': value}
)
return obj

def __deepcopy__(self, memo):
result = super(forms.ChoiceField, self).__deepcopy__(memo)
result.queryset = self.queryset # self.queryset calls clone()
Expand Down Expand Up @@ -169,7 +175,7 @@ def clean(self, value):
return []
if not isinstance(value, (list, tuple)):
raise forms.ValidationError(self.error_messages['list'])

qs = self.queryset
try:
qs = qs.filter(pk__in=value)
Expand All @@ -193,8 +199,8 @@ def prepare_value(self, value):
sup = super(DocumentMultipleChoiceField, self)
return [sup.prepare_value(v) for v in value]
return super(DocumentMultipleChoiceField, self).prepare_value(value)


class ListField(forms.Field):
default_error_messages = {
'invalid': _('Enter a list of values.'),
Expand All @@ -205,23 +211,23 @@ class ListField(forms.Field):
def __init__(self, contained_field, *args, **kwargs):
if 'widget' in kwargs:
self.widget = kwargs.pop('widget')

if isinstance(contained_field, type):
contained_widget = contained_field().widget
else:
contained_widget = contained_field.widget

if isinstance(contained_widget, type):
contained_widget = contained_widget()
self.widget = self.widget(contained_widget)

super(ListField, self).__init__(*args, **kwargs)

if isinstance(contained_field, type):
self.contained_field = contained_field(required=self.required)
else:
self.contained_field = contained_field

if not hasattr(self, 'empty_values'):
self.empty_values = list(EMPTY_VALUES)

Expand All @@ -241,7 +247,7 @@ def clean(self, value):
return []
else:
raise ValidationError(self.error_messages['invalid'])

for field_value in value:
try:
clean_data.append(self.contained_field.clean(field_value))
Expand All @@ -262,12 +268,12 @@ def clean(self, value):
def _has_changed(self, initial, data):
if initial is None:
initial = ['' for x in range(0, len(data))]

for initial, data in zip(initial, data):
if self.contained_field._has_changed(initial, data):
return True
return False

def prepare_value(self, value):
value = [] if value is None else value
value = super(ListField, self).prepare_value(value)
Expand All @@ -290,30 +296,30 @@ def __init__(self, contained_field, max_key_length=None,
*args, **kwargs):
if 'widget' in kwargs:
self.widget = kwargs.pop('widget')

if isinstance(contained_field, type):
contained_widget = contained_field().widget
else:
contained_widget = contained_field.widget

if isinstance(contained_widget, type):
contained_widget = contained_widget()
self.widget = self.widget(contained_widget)

super(MapField, self).__init__(*args, **kwargs)

if isinstance(contained_field, type):
field_kwargs['required'] = self.required
self.contained_field = contained_field(**field_kwargs)
else:
self.contained_field = contained_field

self.key_validators = key_validators
if min_key_length is not None:
self.key_validators.append(MinLengthValidator(int(min_key_length)))
if max_key_length is not None:
self.key_validators.append(MaxLengthValidator(int(max_key_length)))

# type of field used to store the dicts value
if not hasattr(self, 'empty_values'):
self.empty_values = list(EMPTY_VALUES)
Expand Down Expand Up @@ -351,34 +357,34 @@ def clean(self, value):
return {}
else:
raise ValidationError(self.error_messages['invalid'])

# sort out required => at least one element must be in there
for key, val in value.items():
# ignore empties. Can they even come up here?
if key in self.empty_values and val in self.empty_values:
continue

try:
val = self.contained_field.clean(val)
except ValidationError as e:
# Collect all validation errors in a single list, which we'll
# raise at the end of clean(), rather than raising a single
# exception for the first error we encounter.
errors.extend(e.messages)

try:
self._validate_key(key)
except ValidationError as e:
# Collect all validation errors in a single list, which we'll
# raise at the end of clean(), rather than raising a single
# exception for the first error we encounter.
errors.extend(e.messages)

clean_data[key] = val

if self.contained_field.required:
self.contained_field.required = False

if errors:
raise ValidationError(errors)

Expand Down
Loading