Skip to content

Commit

Permalink
support default values on fields (and models)
Browse files Browse the repository at this point in the history
  • Loading branch information
domenkozar committed Nov 11, 2015
1 parent d2f5f15 commit 842632d
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 6 deletions.
11 changes: 10 additions & 1 deletion import_export/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from django.core.exceptions import ObjectDoesNotExist
from django.db.models.manager import Manager
from django.db.models.fields import NOT_PROVIDED


class Field(object):
Expand All @@ -22,11 +23,14 @@ class Field(object):
``readonly`` boolean value defines that if this field will be assigned
to object during import.
``default`` value returned by :meth`clean` if returned value evaluates to False
"""

def __init__(self, attribute=None, column_name=None, widget=None,
readonly=False):
default=None, readonly=False):
self.attribute = attribute
self.default = default
self.column_name = column_name
if not widget:
widget = widgets.Widget()
Expand Down Expand Up @@ -59,6 +63,11 @@ def clean(self, data):
except ValueError as e:
raise ValueError("Column '%s': %s" % (self.column_name, e))

if not value and self.default != NOT_PROVIDED:
if callable(self.default):
self.default = self.default()
return self.default

return value

def get_value(self, obj):
Expand Down
12 changes: 8 additions & 4 deletions import_export/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def __new__(cls, name, bases, attrs):

# Add direct options
options = getattr(new_class, 'Meta', None)
for option in [option for option in dir(options)
for option in [option for option in dir(options)
if not option.startswith('_')]:
setattr(meta, option, getattr(options, option))
new_class._meta = meta
Expand Down Expand Up @@ -569,8 +569,13 @@ def field_from_django_field(self, field_name, django_field, readonly):

FieldWidget = self.widget_from_django_field(django_field)
widget_kwargs = self.widget_kwargs_for_field(field_name)
field = Field(attribute=field_name, column_name=field_name,
widget=FieldWidget(**widget_kwargs), readonly=readonly)
field = Field(
attribute=field_name,
column_name=field_name,
widget=FieldWidget(**widget_kwargs),
readonly=readonly,
default=django_field.default,
)
return field

def get_import_id_fields(self):
Expand Down Expand Up @@ -598,4 +603,3 @@ def modelresource_factory(model, resource_class=ModelResource):

metaclass = ModelDeclarativeMetaclass
return metaclass(class_name, (resource_class,), class_attrs)

4 changes: 4 additions & 0 deletions tests/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ class Profile(models.Model):

class Entry(models.Model):
user = models.ForeignKey('auth.User')


class WithDefault(models.Model):
name = models.CharField('Default', max_length=75, blank=True, default=lambda: 'foo_bar')
12 changes: 11 additions & 1 deletion tests/core/tests/resources_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from import_export import results
from import_export.instance_loaders import ModelInstanceLoader

from core.models import Book, Author, Category, Entry, Profile
from core.models import Book, Author, Category, Entry, Profile, WithDefault

try:
from django.utils.encoding import force_text
Expand Down Expand Up @@ -115,6 +115,12 @@ class Meta:
exclude = ('imported', )


class WithDefaultResource(resources.ModelResource):
class Meta:
model = WithDefault
fields = ('name',)


class ModelResourceTest(TestCase):
def setUp(self):
self.resource = BookResource()
Expand Down Expand Up @@ -154,6 +160,10 @@ def test_init_instance(self):
instance = self.resource.init_instance()
self.assertIsInstance(instance, Book)

def test_default(self):
self.assertTrue(callable(WithDefaultResource.fields['name'].default))
self.assertEquals(WithDefaultResource.fields['name'].clean({'name': ''}), 'foo_bar')

def test_get_instance(self):
instance_loader = self.resource._meta.instance_loader_class(
self.resource)
Expand Down

0 comments on commit 842632d

Please sign in to comment.