Make deep copy of fileds from class attr to instance attr (#550)
* Make deep copy of fileds from class attr to instance attr The fields resource class attribute is the *class-wide* definition of fields. Because a particular *instance* of the class might want to alter self.fields, we create self.fields here by copying cls.fields. Instances should always modify self.fields; they should not modify cls.fields. * Update test for resource fields Test checks that resource instance *fields* attr doesn't refer to attr *fields* of resource class
This commit is contained in:
parent
8562268e0f
commit
7045e39425
|
@ -192,6 +192,14 @@ class Resource(six.with_metaclass(DeclarativeMetaclass)):
|
|||
representations and handle importing and exporting data.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# The fields class attribute is the *class-wide* definition of
|
||||
# fields. Because a particular *instance* of the class might want to
|
||||
# alter self.fields, we create self.fields here by copying cls.fields.
|
||||
# Instances should always modify self.fields; they should not modify
|
||||
# cls.fields.
|
||||
self.fields = deepcopy(self.fields)
|
||||
|
||||
@classmethod
|
||||
def get_result_class(self):
|
||||
"""
|
||||
|
@ -233,16 +241,15 @@ class Resource(six.with_metaclass(DeclarativeMetaclass)):
|
|||
"""
|
||||
return [self.fields[f] for f in self.get_export_order()]
|
||||
|
||||
@classmethod
|
||||
def get_field_name(cls, field):
|
||||
def get_field_name(self, field):
|
||||
"""
|
||||
Returns the field name for a given field.
|
||||
"""
|
||||
for field_name, f in cls.fields.items():
|
||||
for field_name, f in self.fields.items():
|
||||
if f == field:
|
||||
return field_name
|
||||
raise AttributeError("Field %s does not exists in %s resource" % (
|
||||
field, cls))
|
||||
field, self.__class__))
|
||||
|
||||
def init_instance(self, row=None):
|
||||
raise NotImplementedError()
|
||||
|
|
|
@ -24,6 +24,11 @@ from ..models import (
|
|||
WithFloatField,
|
||||
)
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError:
|
||||
from django.utils.datastructures import SortedDict as OrderedDict
|
||||
|
||||
try:
|
||||
from django.utils.encoding import force_text
|
||||
except ImportError:
|
||||
|
@ -45,8 +50,35 @@ class ResourceTestCase(TestCase):
|
|||
self.my_resource = MyResource()
|
||||
|
||||
def test_fields(self):
|
||||
fields = self.my_resource.fields
|
||||
self.assertIn('name', fields)
|
||||
"""Check that fields were determined correctly """
|
||||
|
||||
# check that our fields were determined
|
||||
self.assertIn('name', self.my_resource.fields)
|
||||
|
||||
# check that resource instance fields attr isn't link to resource cls
|
||||
# fields
|
||||
self.assertFalse(
|
||||
MyResource.fields is self.my_resource.fields
|
||||
)
|
||||
|
||||
# dynamically add new resource field into resource instance
|
||||
self.my_resource.fields.update(
|
||||
OrderedDict([
|
||||
('new_field', fields.Field()),
|
||||
])
|
||||
)
|
||||
|
||||
# check that new field in resource instance fields
|
||||
self.assertIn(
|
||||
'new_field',
|
||||
self.my_resource.fields
|
||||
)
|
||||
|
||||
# check that new field not in resource cls fields
|
||||
self.assertNotIn(
|
||||
'new_field',
|
||||
MyResource.fields
|
||||
)
|
||||
|
||||
def test_field_column_name(self):
|
||||
field = self.my_resource.fields['name']
|
||||
|
|
Loading…
Reference in New Issue