Skip to content

Commit 8aa7339

Browse files
committed
first commit
0 parents  commit 8aa7339

22 files changed

+574
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.pyc
2+
*~

.travis.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
language: python
2+
notifications:
3+
email: false
4+
env:
5+
global:
6+
python:
7+
- 2.6
8+
- 2.7
9+
- 3.3
10+
- 3.4
11+
install:
12+
- pip install git+https://github.com/chfw/pyexcel-io.git
13+
- pip install git+https://github.com/chfw/pyexcel.git
14+
- pip install git+https://github.com/chfw/pyexcel-webio.git
15+
- pip install git+https://github.com/chfw/pyexcel-xls.git
16+
- pip install -r requirements.txt
17+
- pip install -r test_requirements.txt --use-mirrors
18+
- if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install pyexcel-ods; fi
19+
- if [[ $TRAVIS_PYTHON_VERSION == "2.7" ]]; then pip install pyexcel-ods; fi
20+
- if [[ $TRAVIS_PYTHON_VERSION == "3.3" ]]; then pip install git+https://github.com/chfw/ezodf.git; fi
21+
- if [[ $TRAVIS_PYTHON_VERSION == "3.4" ]]; then pip install git+https://github.com/chfw/ezodf.git; fi
22+
- if [[ $TRAVIS_PYTHON_VERSION == "3.3" ]]; then pip install pyexcel-ods3; fi
23+
- if [[ $TRAVIS_PYTHON_VERSION == "3.4" ]]; then pip install pyexcel-ods3; fi
24+
script:
25+
make test
26+
after_success:
27+
coveralls

README.rst

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
==============================================================
2+
django-excel - Let you focus on data, instead of file formats
3+
==============================================================
4+
5+
.. image:: https://api.travis-ci.org/chfw/django-excel.svg?branch=master
6+
:target: http://travis-ci.org/chfw/django-excel
7+
8+
.. image:: https://coveralls.io/repos/chfw/django-excel/badge.png?branch=master
9+
:target: https://coveralls.io/r/chfw/django-excel?branch=master
10+
11+
.. image:: https://readthedocs.org/projects/django-excel/badge/?version=latest
12+
:target: http://django-excel.readthedocs.org/en/latest/
13+
14+
.. image:: https://pypip.in/version/django-excel/badge.png
15+
:target: https://pypi.python.org/pypi/django-excel
16+
17+
.. image:: https://pypip.in/d/django-excel/badge.png
18+
:target: https://pypi.python.org/pypi/django-excel
19+
20+
.. image:: https://pypip.in/py_versions/django-excel/badge.png
21+
:target: https://pypi.python.org/pypi/django-excel
22+
23+
.. image:: http://img.shields.io/gittip/chfw.svg
24+
:target: https://gratipay.com/chfw/
25+
26+
**django-excel** is based on `pyexcel <https://github.com/chfw/pyexcel>`_ and makes it easy to consume/produce information stored in excel files over HTTP protocol as well as on file system. This library can turn the excel data into Pythonic a list of lists, a list of records(dictionaries), dictionaries of lists. And vice versa. Hence it lets you focus on data in Flask based web development, instead of file formats.
27+
28+
The idea originated from the problem of the illiteracy of excel file formats of non-technical office workers: such as office assistant, human resource administrator. There is nothing with the un-deniable fact that some people do not know the difference among various excel formats. It becomes usability problem to those people when a web service cannot parse the excel file that they saved using Microsoft Excel. Instead of training those people about file formats, this library helps web developers to handle most of the excel file formats by unifying the programming interface to most of the excel readers and writers.
29+
30+
The highlighted features are:
31+
32+
#. turn uploaded excel file directly into Python data struture
33+
#. pass Python data structures as an excel file download
34+
#. provide data persistence as an excel file in server side
35+
#. supports csv, tsv, csvz, tsvz by default and other formats are supported via the following plugins:
36+
37+
Available Plugins
38+
=================
39+
40+
================ ========================================================================
41+
Plugins Supported file formats
42+
================ ========================================================================
43+
`pyexcel-xls`_ xls, xlsx(r), xlsm(r)
44+
`pyexcel-xlsx`_ xlsx
45+
`pyexcel-ods`_ ods (python 2.6, 2.7)
46+
`pyexcel-ods3`_ ods (python 2.7, 3.3, 3.4)
47+
`pyexcel-text`_ (write only)json, rst, mediawiki,latex, grid, pipe, orgtbl, plain simple
48+
================ ========================================================================
49+
50+
.. _pyexcel-xls: https://github.com/chfw/pyexcel-xls
51+
.. _pyexcel-xlsx: https://github.com/chfw/pyexcel-xlsx
52+
.. _pyexcel-ods: https://github.com/chfw/pyexcel-ods
53+
.. _pyexcel-ods3: https://github.com/chfw/pyexcel-ods3
54+
.. _pyexcel-text: https://github.com/chfw/pyexcel-text
55+
56+
57+
Known constraints
58+
==================
59+
60+
Fonts, colors and charts are not supported.
61+
62+
Installation
63+
============
64+
You can install it via pip::
65+
66+
$ pip install django-excel
67+
68+
69+
or clone it and install it::
70+
71+
$ git clone http://github.com/chfw/django-pyexcel.git
72+
$ cd django-excel
73+
$ python setup.py install
74+
75+
Installation of individual plugins , please refer to individual plugin page.
76+
77+
78+
Dependencies
79+
=============
80+
81+
* pyexcel

django_excel/__init__.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from django.core.files.uploadhandler import MemoryFileUploadHandler, TemporaryFileUploadHandler
2+
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
3+
from django.http import HttpResponse
4+
import pyexcel as pe
5+
import pyexcel_webio as webio
6+
7+
8+
class ExcelMemoryFile(webio.ExcelInput, InMemoryUploadedFile):
9+
def _get_file_extension(self):
10+
extension = self.name.split(".")[1]
11+
return extension
12+
13+
def load_single_sheet(self, sheet_name=None, **keywords):
14+
return pe.load_from_memory(self._get_file_extension(), self.file.read(), sheet_name, **keywords)
15+
16+
def load_book(self):
17+
return pe.load_book_from_memory(self._get_file_extension(), self.file.read())
18+
19+
20+
class ExcelFile(webio.ExcelInput, TemporaryUploadedFile):
21+
def load_single_sheet(self, sheet_name=None, **keywords):
22+
return pe.load(self.file.replace(".upload", ""), sheet_name, **keywords)
23+
24+
def load_book(self):
25+
return pe.load_book(self.file.replace(".upload", ""))
26+
27+
28+
class ExcelMemoryFileUploadHandler(MemoryFileUploadHandler):
29+
def file_complete(self, file_size):
30+
self.file.seek(0)
31+
return ExcelMemoryFile(
32+
file=self.file,
33+
field_name=self.field_name,
34+
name=self.file_name,
35+
content_type=self.content_type,
36+
size=file_size,
37+
charset=self.charset,
38+
content_type_extra=self.content_type_extra
39+
)
40+
41+
class TemporaryExcelFileUploadHandler(TemporaryFileUploadHandler):
42+
def file_complete(self, file_size):
43+
self.file.seek(0)
44+
return ExcelMemoryFile(
45+
file=self.file,
46+
field_name=self.field_name,
47+
name=self.file_name,
48+
content_type=self.content_type,
49+
size=file_size,
50+
charset=self.charset,
51+
content_type_extra=self.content_type_extra
52+
)
53+
54+
webio.ExcelResponse = HttpResponse
55+
56+
from pyexcel_webio import (
57+
make_response,
58+
make_response_from_array,
59+
make_response_from_dict,
60+
make_response_from_records,
61+
make_response_from_book_dict
62+
)

manage.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env python
2+
import os
3+
import sys
4+
5+
if __name__ == "__main__":
6+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
7+
8+
from django.core.management import execute_from_command_line
9+
10+
execute_from_command_line(sys.argv)

mysite/__init__.py

Whitespace-only changes.

mysite/settings.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"""
2+
Django settings for mysite project.
3+
4+
For more information on this file, see
5+
https://docs.djangoproject.com/en/1.7/topics/settings/
6+
7+
For the full list of settings and their values, see
8+
https://docs.djangoproject.com/en/1.7/ref/settings/
9+
"""
10+
11+
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
12+
import os
13+
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
14+
15+
16+
# Quick-start development settings - unsuitable for production
17+
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
18+
19+
# SECURITY WARNING: keep the secret key used in production secret!
20+
SECRET_KEY = '&kzg)(b_xt1*nyp-s97ibt01b7p+67#&-brmb_nqj&dn_%q6tc'
21+
22+
# SECURITY WARNING: don't run with debug turned on in production!
23+
DEBUG = True
24+
25+
TEMPLATE_DEBUG = True
26+
27+
ALLOWED_HOSTS = []
28+
29+
TEMPLATE_DIRS = [(
30+
BASE_DIR + '/templates/'
31+
)]
32+
# Application definition
33+
34+
FILE_UPLOAD_HANDLERS = ("django_excel.ExcelMemoryFileUploadHandler",
35+
"django_excel.TemporaryExcelFileUploadHandler")
36+
37+
INSTALLED_APPS = (
38+
'django.contrib.admin',
39+
'django.contrib.auth',
40+
'django.contrib.contenttypes',
41+
'django.contrib.sessions',
42+
'django.contrib.messages',
43+
'django.contrib.staticfiles',
44+
'polls'
45+
)
46+
47+
MIDDLEWARE_CLASSES = (
48+
'django.contrib.sessions.middleware.SessionMiddleware',
49+
'django.middleware.common.CommonMiddleware',
50+
'django.middleware.csrf.CsrfViewMiddleware',
51+
'django.contrib.auth.middleware.AuthenticationMiddleware',
52+
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
53+
'django.contrib.messages.middleware.MessageMiddleware',
54+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
55+
)
56+
57+
ROOT_URLCONF = 'mysite.urls'
58+
59+
WSGI_APPLICATION = 'mysite.wsgi.application'
60+
61+
62+
# Database
63+
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
64+
65+
DATABASES = {
66+
'default': {
67+
'ENGINE': 'django.db.backends.sqlite3',
68+
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
69+
}
70+
}
71+
72+
# Internationalization
73+
# https://docs.djangoproject.com/en/1.7/topics/i18n/
74+
75+
LANGUAGE_CODE = 'en-us'
76+
77+
TIME_ZONE = 'UTC'
78+
79+
USE_I18N = True
80+
81+
USE_L10N = True
82+
83+
USE_TZ = True
84+
85+
86+
# Static files (CSS, JavaScript, Images)
87+
# https://docs.djangoproject.com/en/1.7/howto/static-files/
88+
89+
STATIC_URL = '/static/'

mysite/urls.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django.conf.urls import patterns, include, url
2+
from django.contrib import admin
3+
4+
urlpatterns = patterns('',
5+
# Examples:
6+
# url(r'^$', 'mysite.views.home', name='home'),
7+
# url(r'^blog/', include('blog.urls')),
8+
9+
url(r'^admin/', include(admin.site.urls)),
10+
url(r'^polls/', include('polls.urls'))
11+
)

mysite/wsgi.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
WSGI config for mysite project.
3+
4+
It exposes the WSGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
8+
"""
9+
10+
import os
11+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
12+
13+
from django.core.wsgi import get_wsgi_application
14+
application = get_wsgi_application()

polls/__init__.py

Whitespace-only changes.

polls/admin.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.contrib import admin
2+
3+
# Register your models here.

polls/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.db import models
2+
3+
# Create your models here.

polls/tests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

polls/urls.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django.conf.urls import patterns, url
2+
3+
from polls import views
4+
5+
urlpatterns = patterns(
6+
'',
7+
url(r'^$', views.upload, name='uplink'),
8+
url(r'^download/(.*)', views.download, name="download"),
9+
url(r'^exchange/(.*)', views.exchange, name="exchange"),
10+
url(r'^parse/(.*)', views.parse, name="parse")
11+
)

polls/views.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from django.shortcuts import render_to_response
2+
from django.http import HttpResponse, HttpResponseBadRequest, JsonResponse
3+
from django import forms
4+
from django.template import RequestContext
5+
import django_excel as excel
6+
import pyexcel.ext.xls
7+
import pyexcel.ext.xlsx
8+
import pyexcel.ext.ods
9+
10+
data = [
11+
[1, 2, 3],
12+
[4, 5, 6]
13+
]
14+
15+
class UploadFileForm(forms.Form):
16+
file = forms.FileField()
17+
18+
19+
# Create your views here.
20+
def upload(request):
21+
if request.method == "POST":
22+
import pdb; pdb.set_trace()
23+
form = UploadFileForm(request.POST, request.FILES)
24+
if form.is_valid():
25+
filehandle = request.FILES['file']
26+
return excel.make_response(filehandle.get_sheet(), "csv")
27+
else:
28+
form = UploadFileForm()
29+
return render_to_response('upload_form.html', {'form': form}, context_instance=RequestContext(request))
30+
31+
def download(request, file_type):
32+
sheet = excel.pe.Sheet(data)
33+
return excel.make_response(sheet, file_type)
34+
35+
def exchange(request, file_type):
36+
form = UploadFileForm(request.POST, request.FILES)
37+
if form.is_valid():
38+
filehandle = request.FILES['file']
39+
return excel.make_response(filehandle.get_sheet(), file_type)
40+
else:
41+
return HttpResponseBadRequest()
42+
43+
def parse(request, data_struct_type):
44+
form = UploadFileForm(request.POST, request.FILES)
45+
if form.is_valid():
46+
filehandle = request.FILES['file']
47+
if data_struct_type == "array":
48+
return JsonResponse({"result":filehandle.get_array()})
49+
elif data_struct_type == "dict":
50+
return JsonResponse(filehandle.get_dict())
51+
elif data_struct_type == "records":
52+
return JsonResponse({"result":filehandle.get_records()})
53+
elif data_struct_type == "book":
54+
return JsonResponse(filehandle.get_book().to_dict())
55+
elif data_struct_type == "book_dict":
56+
return JsonResponse(filehandle.get_book_dict())
57+
else:
58+
return HttpResponseBadRequest()
59+
else:
60+
return HttpResponseBadRequest()
61+

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pyexcel>=0.1.2
2+
pyexcel-webio>=0.0.1
3+
Django==1.7.1

0 commit comments

Comments
 (0)