Skip to content

Commit db00be1

Browse files
committed
document saving to django database
1 parent 43c4a2b commit db00be1

File tree

11 files changed

+160
-8
lines changed

11 files changed

+160
-8
lines changed

doc/source/choice-admin.png

17.8 KB
Loading

doc/source/choice-sheet.png

8.95 KB
Loading

doc/source/download-dialog.png

13 KB
Loading

doc/source/import-page.png

17.6 KB
Loading

doc/source/index.rst

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,137 @@ Please open the file **polls/views.py** and focus on the following code section:
9191
form = UploadFileForm()
9292
return render_to_response('upload_form.html', {'form': form}, context_instance=RequestContext(request))
9393

94-
**UploadFileForm** is html widget for file upload form in the html page. Then look down at **filehandle**. It is an instance of either ExcelInMemoryUploadedFile or TemporaryUploadedExcelFile, which inherit ExcelMixin and hence have a list of conversion methods to call, such as get_sheet, get_array, etc. :meth:`~django_excel.make_response` converts :class:`~pyexcel.Sheet` instance obtained via :meth:`~django_excel.ExcelMixin.get_sheet` into a csv file for download. Please feel free to change those functions according to :ref:`the mapping table <data-types-and-its-conversion-funcs>`.
94+
**UploadFileForm** is html widget for file upload form in the html page. Then look down at **filehandle**. It is an instance of either ExcelInMemoryUploadedFile or TemporaryUploadedExcelFile, which inherit ExcelMixin and hence have a list of conversion methods to call, such as get_sheet, get_array, etc.
9595

96-
... to be continued ..
96+
For the response, :meth:`~django_excel.make_response` converts :class:`~pyexcel.Sheet` instance obtained via :meth:`~django_excel.ExcelMixin.get_sheet` into a csv file for download.
97+
98+
Please feel free to change those functions according to :ref:`the mapping table <data-types-and-its-conversion-funcs>`.
99+
100+
Handle data import
101+
++++++++++++++++++++++++++++++
102+
103+
This example shows how to import uploaded excel file into django models. We are going to import *sample-data.xls*
104+
105+
.. table:: Sheet 1 of sample-data.xls
106+
107+
============================================ ============ =================
108+
Question Text Publish Date Unique Identifier
109+
============================================ ============ =================
110+
What is your favourite programming language? 28/01/15 language
111+
What is your favourite IDE? 29/01/15 ide
112+
============================================ ============ =================
113+
114+
.. table:: Sheet 2 of sample-data.xls
115+
116+
========== ============== ======
117+
Question Choice Votes
118+
========== ============== ======
119+
language Java 0
120+
language C++ 0
121+
language C 0
122+
ide Eclipse 0
123+
ide Visual Studio 0
124+
ide PyCharm 0
125+
ide IntelliJ 0
126+
========== ============== ======
127+
128+
into the following data models::
129+
130+
class Question(models.Model):
131+
question_text = models.CharField(max_length=200)
132+
pub_date = models.DateTimeField('date published')
133+
slug = models.CharField(max_length=10, unique=True, default="question")
134+
135+
136+
class Choice(models.Model):
137+
question = models.ForeignKey(Question)
138+
choice_text = models.CharField(max_length=200)
139+
votes = models.IntegerField(default=0)
140+
141+
.. note::
142+
Except the added "slug" field, **Question** and **Choice** are copied from Django tutoial part 1.
143+
144+
Please visit this link http://localhost:8000/import/, you shall see this upload form:
145+
146+
.. image:: import-page.png
147+
148+
Please then select *sample-data.xls* and upload. Then visit the admin page http://localhost:8000/admin/polls/question, you shall see questions have been populated:
149+
150+
.. image:: question-admin.png
151+
152+
.. note::
153+
The admin user credentials are: user name: admin, password: admin
154+
155+
And choices too:
156+
157+
.. image:: choice-admin.png
158+
159+
You may use admin interface to delete all those objects and try again.
160+
161+
Now please open views.py and focus on this part of code::
162+
163+
def import_data(request):
164+
if request.method == "POST":
165+
form = UploadFileForm(request.POST, request.FILES)
166+
def choice_func(row):
167+
print row[0]
168+
q = Question.objects.filter(slug=row[0])[0]
169+
row[0] = q
170+
return row
171+
if form.is_valid():
172+
request.FILES['file'].save_book_to_database(
173+
models=[
174+
(Question, ['question_text', 'pub_date', 'slug'], None, 0),
175+
(Choice, ['question', 'choice_text', 'votes'], choice_func, 0)
176+
]
177+
)
178+
return HttpResponse("OK", status=200)
179+
else:
180+
return HttpResponseBadRequest()
181+
else:
182+
...
183+
184+
The star is :meth:`~django_excel.save_book_to_database`. The parameter **models** can be a list of django models or a list of tuples, each of which contains:
185+
186+
1. django model (**compulsory**)
187+
2. an array of model fields or a dicionary of key maps
188+
3. custom formating fuction
189+
4. the index of the row that has the field names
190+
5. the index of the column that has the field names
191+
192+
When an array of model fields is supplied in the second member in the tuple, the names of the supplied fields should match the field names of the corresponding django model(the first member in the tuple) and the sequence of the supplied fields shall match the one in the uploaded excel sheet. For example::
193+
194+
(Question, ['question_text', 'pub_date', 'slug'], None, 0)
195+
196+
When a dictionary of key maps is supplied, its keys should be the field names in the uploaded excel sheet and the value should be the actual field name in the corresponding django model. For example::
197+
198+
(Question,{"Question Text": "question_text",
199+
"Publish Date": "pub_date",
200+
"Unique Identifier": "slug"}, None, 0)
201+
202+
The custom formatting function is needed when the data from the excel sheet needs translation before data import. For example, **Choice** has a foreign key to **Question**. When choice data are to be imported, "Question" column needs to be translated to a question instance. In our example, "Question" column in "Sheet 2" contains the values appeared in "Unique Identifier" column in "Sheet 1".
203+
204+
Handle data export
205+
++++++++++++++++++++++++++++++
206+
207+
This section shows how to export the data in your models as an excel file. After you have completed the previous section, you can visit http://localhost:8000/export/book and you shall get a file download dialog:
208+
209+
.. image:: download-dialog.png
210+
211+
Please save and open it. You shall see these data in your window:
212+
213+
.. image:: question-sheet.png
214+
.. image:: choice-sheet.png
215+
216+
Now let's examine the code behind this::
217+
218+
def export_data(request, atype):
219+
if atype == "sheet":
220+
return excel.make_response_from_a_table(Question, 'xls')
221+
elif atype == "book":
222+
return excel.make_response_from_tables([Question, Choice], 'xls')
223+
224+
:meth:`~django_excel.make_response_from_tables` does all what is needed: read out the data, convert them into xls and give it the browser. And what you need to do is to give a list of models to be exported and a file type. As you have noticed, you can visit http://localhost:8000/exportsheet and will get **Question** exported as a single sheet file.
97225

98226
.. _data-types-and-its-conversion-funcs:
99227

doc/source/question-admin.png

27.8 KB
Loading

doc/source/question-sheet.png

8.41 KB
Loading

document.bat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
python setup.py install
2+
rem del doc\source\generated\*.rst
3+
rem sphinx-autogen -o doc\source\generated doc\source\index.rst
4+
sphinx-build -b html doc\source doc\build

polls/models.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,14 @@ class Question(models.Model):
66
pub_date = models.DateTimeField('date published')
77
slug = models.CharField(max_length=10, unique=True, default="question")
88

9+
def __str__(self):
10+
return self.question_text
11+
912

1013
class Choice(models.Model):
1114
question = models.ForeignKey(Question)
1215
choice_text = models.CharField(max_length=200)
13-
votes = models.IntegerField(default=0)
16+
votes = models.IntegerField(default=0)
17+
18+
def __str__(self):
19+
return self.choice_text

polls/views.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,14 @@ def upload(request):
3232
return excel.make_response(filehandle.get_sheet(), "csv")
3333
else:
3434
form = UploadFileForm()
35-
return render_to_response('upload_form.html', {'form': form}, context_instance=RequestContext(request))
35+
return render_to_response(
36+
'upload_form.html',
37+
{
38+
'form': form,
39+
'title': 'Excel file upload and download example',
40+
'header': 'Please choose any excel file from your cloned repository:'
41+
},
42+
context_instance=RequestContext(request))
3643

3744
def download(request, file_type):
3845
sheet = excel.pe.Sheet(data)
@@ -64,8 +71,15 @@ def choice_func(row):
6471
return HttpResponseBadRequest()
6572
else:
6673
form = UploadFileForm()
67-
return render_to_response('upload_form.html', {'form': form}, context_instance=RequestContext(request))
68-
74+
return render_to_response(
75+
'upload_form.html',
76+
{
77+
'form': form,
78+
'title': 'Import excel data into database example',
79+
'header': 'Please upload sample-data.xls:'
80+
},
81+
context_instance=RequestContext(request))
82+
6983

7084
def import_dataa(request):
7185
if request.method == "POST":

0 commit comments

Comments
 (0)