Initial import
This commit is contained in:
parent
020a17b051
commit
704c9a6a66
|
@ -0,0 +1,3 @@
|
||||||
|
====================
|
||||||
|
django-import-export
|
||||||
|
====================
|
|
@ -0,0 +1,2 @@
|
||||||
|
VERSION = (0, 0, '1dev')
|
||||||
|
__version__ = '.'.join(map(str, VERSION))
|
|
@ -0,0 +1,107 @@
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
import tablib
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class RowResult(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.errors = []
|
||||||
|
self.orig_fields = []
|
||||||
|
self.fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class Result(list):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(Result, self).__init__(*args, **kwargs)
|
||||||
|
self.base_errors = []
|
||||||
|
|
||||||
|
def row_errors(self):
|
||||||
|
return [(i, row.errors) for i, row in enumerate(self) if row.errors]
|
||||||
|
|
||||||
|
def has_errors(self):
|
||||||
|
return self.base_errors or self.row_errors()
|
||||||
|
|
||||||
|
|
||||||
|
class Importer(object):
|
||||||
|
model = None
|
||||||
|
format = None
|
||||||
|
import_code = "ID"
|
||||||
|
raise_errors = True
|
||||||
|
dry_run = True
|
||||||
|
mapping = None
|
||||||
|
|
||||||
|
def __init__(self, f, **kwargs):
|
||||||
|
self.f = f
|
||||||
|
for key, value in kwargs.iteritems():
|
||||||
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
def get_mapping(self):
|
||||||
|
if self.mapping:
|
||||||
|
return self.mapping
|
||||||
|
mapping = [(f.verbose_name, f.name) for f in self.model._meta.fields]
|
||||||
|
return OrderedDict(mapping)
|
||||||
|
|
||||||
|
def load_dataset(self):
|
||||||
|
text = unicode(self.f.read(), 'cp1250').encode('utf-8')
|
||||||
|
if not self.format:
|
||||||
|
self.data = tablib.import_set(text)
|
||||||
|
else:
|
||||||
|
self.data = tablib.Dataset()
|
||||||
|
self.format.import_set(self.data, text)
|
||||||
|
|
||||||
|
def get_instance(self, row):
|
||||||
|
return self.model.objects.get(**{
|
||||||
|
self.get_mapping()[self.import_code]: row[self.import_code]
|
||||||
|
})
|
||||||
|
|
||||||
|
def init_instance(self, row):
|
||||||
|
return self.model()
|
||||||
|
|
||||||
|
def get_or_init_instance(self, row):
|
||||||
|
try:
|
||||||
|
instance = self.get_instance(row)
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
instance = self.init_instance(row)
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def set_instance_attr(self, instance, row, field):
|
||||||
|
setattr(instance, self.get_mapping()[field], row[field])
|
||||||
|
|
||||||
|
def save_instance(self, instance):
|
||||||
|
if not self.dry_run:
|
||||||
|
instance.save()
|
||||||
|
|
||||||
|
def get_representation(self, instance):
|
||||||
|
return [unicode(getattr(instance, f))
|
||||||
|
for f in self.get_mapping().values()]
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
result = Result()
|
||||||
|
try:
|
||||||
|
self.load_dataset()
|
||||||
|
except Exception, e:
|
||||||
|
result.base_errors.append(_('Loading error') +
|
||||||
|
u': %s' % unicode(e))
|
||||||
|
if self.raise_errors:
|
||||||
|
raise
|
||||||
|
return result
|
||||||
|
|
||||||
|
for row in self.data.dict:
|
||||||
|
try:
|
||||||
|
row_result = RowResult()
|
||||||
|
instance = self.get_or_init_instance(row)
|
||||||
|
row_result.orig_fields = self.get_representation(instance)
|
||||||
|
for field in self.get_mapping().keys():
|
||||||
|
self.set_instance_attr(instance, row, field)
|
||||||
|
self.save_instance(instance)
|
||||||
|
row_result.fields = self.get_representation(instance)
|
||||||
|
except Exception, e:
|
||||||
|
row_result.errors.append(unicode(e))
|
||||||
|
if self.raise_errors:
|
||||||
|
raise
|
||||||
|
result.append(row_result)
|
||||||
|
return result
|
|
@ -0,0 +1,2 @@
|
||||||
|
Django>=1.4
|
||||||
|
tablib
|
|
@ -0,0 +1 @@
|
||||||
|
PYTHONPATH=".:tests:$PYTHONPATH" django-admin.py test core --settings=settings
|
|
@ -0,0 +1,30 @@
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
VERSION = __import__("send_instance").__version__
|
||||||
|
|
||||||
|
CLASSIFIERS = [
|
||||||
|
'Framework :: Django',
|
||||||
|
'Intended Audience :: Developers',
|
||||||
|
'License :: OSI Approved :: BSD License',
|
||||||
|
'Operating System :: OS Independent',
|
||||||
|
'Topic :: Software Development',
|
||||||
|
]
|
||||||
|
|
||||||
|
install_requires = [
|
||||||
|
'tablib',
|
||||||
|
'Django>=1.4.2',
|
||||||
|
]
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="django-import-export",
|
||||||
|
description="django-import-export",
|
||||||
|
long_description=open(os.path.join(os.path.dirname(__file__),
|
||||||
|
'README.rst')).read(),
|
||||||
|
version=VERSION,
|
||||||
|
author="Informatika Mihelac",
|
||||||
|
author_email="bmihelac@mihelac.org",
|
||||||
|
url="https://github.com/bmihelac/django-import-export",
|
||||||
|
packages=find_packages(exclude=["tests"]),
|
||||||
|
)
|
|
@ -0,0 +1,2 @@
|
||||||
|
ID,Book name,Author email
|
||||||
|
1,Some book,test@example.com
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Book(models.Model):
|
||||||
|
name = models.CharField('Book name', max_length=100)
|
||||||
|
author_email = models.EmailField('Author email', max_length=75, blank=True)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.name
|
|
@ -0,0 +1,32 @@
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from import_export.core import Importer
|
||||||
|
|
||||||
|
from .models import Book
|
||||||
|
|
||||||
|
|
||||||
|
class BookImporter(Importer):
|
||||||
|
|
||||||
|
model = Book
|
||||||
|
|
||||||
|
|
||||||
|
class ImporterTest(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.filename = os.path.join(os.path.dirname(__file__), 'exports',
|
||||||
|
'books.csv')
|
||||||
|
|
||||||
|
def test_import_create(self):
|
||||||
|
result = BookImporter(open(self.filename), dry_run=False).run()
|
||||||
|
self.assertFalse(result.has_errors())
|
||||||
|
self.assertEqual(Book.objects.count(), 1)
|
||||||
|
|
||||||
|
def test_import_update(self):
|
||||||
|
Book.objects.create(id=1, name="Other book")
|
||||||
|
result = BookImporter(open(self.filename), dry_run=False).run()
|
||||||
|
self.assertFalse(result.has_errors())
|
||||||
|
self.assertEqual(Book.objects.count(), 1)
|
||||||
|
self.assertEqual(Book.objects.all()[0].name, "Some book")
|
||||||
|
self.assertNotEqual(result[0].orig_fields[1], result[0].fields[1])
|
|
@ -0,0 +1,20 @@
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': 'haystack_tests.db',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.sites',
|
||||||
|
|
||||||
|
'import_export',
|
||||||
|
|
||||||
|
'core',
|
||||||
|
]
|
||||||
|
|
||||||
|
SITE_ID = 1
|
Loading…
Reference in New Issue