diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo index ec48ec6..b661036 100644 Binary files a/locale/en/LC_MESSAGES/django.mo and b/locale/en/LC_MESSAGES/django.mo differ diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 3811b8f..76f0867 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-10-30 13:41+0100\n" +"POT-Creation-Date: 2017-10-31 21:09+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -201,7 +201,7 @@ msgid "Place of residence" msgstr "Place of residence" #: .\members\models.py:19 .\members\models.py:70 -#: .\members\templates\member_add_many.html:35 +#: .\members\templates\member_add_many.html:39 msgid "AYY" msgstr "AYY" @@ -225,7 +225,7 @@ msgstr "Source" msgid "Cash" msgstr "Cash" -#: .\members\models.py:72 .\members\templates\member_add_many.html:36 +#: .\members\models.py:72 .\members\templates\member_add_many.html:40 msgid "Bank transfer" msgstr "Bank transfer" @@ -284,7 +284,7 @@ msgid "Muista myös maksaa jäsenmaksusi!" msgstr "Don't forget to pay your membership fee!" #: .\members\templates\application_index.html:16 -#: .\members\templates\member_add_many.html:48 +#: .\members\templates\member_add_many.html:55 #: .\members\templates\member_add_many_confirm.html:22 #: .\webapp\templates\kaehmy_list.html:48 msgid "Send" @@ -322,48 +322,50 @@ msgstr "" msgid "" "\n" " Enter member information in CSV format, separate members on " -"separate lines.\n" +"separate lines. \n" +" If a new member already exists in the database, a new payment " +"event will be created for that member instead.\n" " " msgstr "" -#: .\members\templates\member_add_many.html:18 +#: .\members\templates\member_add_many.html:21 +msgid "Format the member table like this:" +msgstr "" + +#: .\members\templates\member_add_many.html:25 msgid "" -"\n" -" first_name, last_name, email_address and place_of_origin should " -"be given string values.\n" -" ayy_member and jas_recipient should be given the value 0 (off) " -"or 1 (on).\n" -" " +"Columns: First name, last name, email address, place of origin, AYY member, " +"JAS recipient" msgstr "" -"\n" -" first_name, last_name, email_address and place_of_origin should " -"be given string values.\n" -" ayy_member and jas_recipient should be given the value 0 (off) " -"or 1 (on).\n" -" " -#: .\members\templates\member_add_many.html:23 -msgid "Syntax" -msgstr "Syntax" - -#: .\members\templates\member_add_many.html:29 -msgid "Data" +#: .\members\templates\member_add_many.html:28 +msgid "Save the file as CSV" msgstr "" #: .\members\templates\member_add_many.html:33 -msgid "Payment source" +msgid "Upload file" msgstr "" #: .\members\templates\member_add_many.html:37 -msgid "Cash payment" +msgid "Payment source" msgstr "" #: .\members\templates\member_add_many.html:41 -msgid "CSV delimiter" +msgid "Cash payment" msgstr "" #: .\members\templates\member_add_many.html:44 msgid "" +"This payment source will be used to create any payments for new members that " +"already exist in the database." +msgstr "" + +#: .\members\templates\member_add_many.html:48 +msgid "CSV delimiter" +msgstr "" + +#: .\members\templates\member_add_many.html:51 +msgid "" "The symbol that is used to separate items in one line. Defaults to " "';' (semicolon)." msgstr "" @@ -469,11 +471,11 @@ msgstr "Member register" msgid "Language" msgstr "Language" -#: .\members\templates\settings.html:20 .\sikweb\base.py:222 +#: .\members\templates\settings.html:20 .\sikweb\base.py:226 msgid "Finnish" msgstr "Finnish" -#: .\members\templates\settings.html:21 .\sikweb\base.py:223 +#: .\members\templates\settings.html:21 .\sikweb\base.py:227 msgid "English" msgstr "English" @@ -560,9 +562,9 @@ msgstr "Successfully updated payment" msgid "Could not update payment object" msgstr "Could not update payment object" -#: .\members\views\utils.py:117 -msgid "Missing \"textfield\" POST request field" -msgstr "Missing \"textfield\" POST request field" +#: .\members\views\utils.py:121 +msgid "Missing CSV file" +msgstr "" #: .\templates\admin\base_site.html:43 msgid "Go" @@ -576,7 +578,7 @@ msgstr "Error" msgid "Back" msgstr "Back" -#: .\templates\footer.html:23 +#: .\templates\footer.html:23 .\webapp\templates\kaehmy_footer.html:23 msgid "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" msgstr "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" @@ -850,7 +852,7 @@ msgstr "" msgid "SIK Admin" msgstr "SIK Admin" -#: .\webapp\templates\base.html:15 +#: .\webapp\templates\base.html:15 .\webapp\templates\kaehmy_base.html:14 msgid "Aalto-yliopiston Sähköinsinöörikilta ry" msgstr "Aalto-yliopiston Sähköinsinöörikilta ry" @@ -1047,5 +1049,26 @@ msgstr "All challenges" msgid "Total challenges:" msgstr "Total challenges:" +#~ msgid "" +#~ "\n" +#~ " first_name, last_name, email_address and place_of_origin " +#~ "should be given string values.\n" +#~ " ayy_member and jas_recipient should be given the value 0 " +#~ "(off) or 1 (on).\n" +#~ " " +#~ msgstr "" +#~ "\n" +#~ " first_name, last_name, email_address and place_of_origin " +#~ "should be given string values.\n" +#~ " ayy_member and jas_recipient should be given the value 0 " +#~ "(off) or 1 (on).\n" +#~ " " + +#~ msgid "Syntax" +#~ msgstr "Syntax" + +#~ msgid "Missing \"textfield\" POST request field" +#~ msgstr "Missing \"textfield\" POST request field" + #~ msgid "Options" #~ msgstr "Options" diff --git a/locale/fi/LC_MESSAGES/django.mo b/locale/fi/LC_MESSAGES/django.mo index a1860c5..9b35184 100644 Binary files a/locale/fi/LC_MESSAGES/django.mo and b/locale/fi/LC_MESSAGES/django.mo differ diff --git a/locale/fi/LC_MESSAGES/django.po b/locale/fi/LC_MESSAGES/django.po index bcde704..688ac0b 100644 --- a/locale/fi/LC_MESSAGES/django.po +++ b/locale/fi/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-10-30 13:41+0100\n" -"PO-Revision-Date: 2017-10-30 14:42+0200\n" +"POT-Creation-Date: 2017-10-31 21:09+0100\n" +"PO-Revision-Date: 2017-10-31 22:11+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: fi\n" @@ -202,7 +202,7 @@ msgid "Place of residence" msgstr "Asuinpaikka" #: .\members\models.py:19 .\members\models.py:70 -#: .\members\templates\member_add_many.html:35 +#: .\members\templates\member_add_many.html:39 msgid "AYY" msgstr "AYY" @@ -226,7 +226,7 @@ msgstr "Lähde" msgid "Cash" msgstr "Käteinen" -#: .\members\models.py:72 .\members\templates\member_add_many.html:36 +#: .\members\models.py:72 .\members\templates\member_add_many.html:40 msgid "Bank transfer" msgstr "Tilisiirto" @@ -283,7 +283,7 @@ msgid "Muista myös maksaa jäsenmaksusi!" msgstr "Muista myös maksaa jäsenmaksusi!" #: .\members\templates\application_index.html:16 -#: .\members\templates\member_add_many.html:48 +#: .\members\templates\member_add_many.html:55 #: .\members\templates\member_add_many_confirm.html:22 #: .\webapp\templates\kaehmy_list.html:48 msgid "Send" @@ -321,50 +321,58 @@ msgstr "Lisää useita" msgid "" "\n" " Enter member information in CSV format, separate members on " -"separate lines.\n" +"separate lines. \n" +" If a new member already exists in the database, a new payment " +"event will be created for that member instead.\n" " " msgstr "" "\n" " Syötä jäsentiedot CSV-formaatissa, erilliset jäsenet omilla " "riveillään.\n" -" " +" Jos jäsenen tiedot ovat jo tietokannassa, tehdään tälle " +"jäsenelle uusi maksutapahtuma." -#: .\members\templates\member_add_many.html:18 +#: .\members\templates\member_add_many.html:21 +msgid "Format the member table like this:" +msgstr "Jäsentele taulukko seuraavasti:" + +#: .\members\templates\member_add_many.html:25 msgid "" -"\n" -" first_name, last_name, email_address and place_of_origin should " -"be given string values.\n" -" ayy_member and jas_recipient should be given the value 0 (off) " -"or 1 (on).\n" -" " +"Columns: First name, last name, email address, place of origin, AYY member, " +"JAS recipient" msgstr "" -"\n" -" first_name, last_name, email_address ja place_of_origin ovat " -"merkkijonoja.\n" -" ayy_member ja jas_recipient ovat joko 0 (off) tai 1 (on).\n" -" " +"Kolumnit: Etunimi, sukunimi, sähköpostiosoite, asuinpaikka, AYY:n jäsen, " +"jäsenmailin vastaanottaja" -#: .\members\templates\member_add_many.html:23 -msgid "Syntax" -msgstr "Syntaksi" - -#: .\members\templates\member_add_many.html:29 -msgid "Data" -msgstr "Data" +#: .\members\templates\member_add_many.html:28 +msgid "Save the file as CSV" +msgstr "Tallenna tiedosto CSV-formaatissa" #: .\members\templates\member_add_many.html:33 +msgid "Upload file" +msgstr "Lataa tiedosto" + +#: .\members\templates\member_add_many.html:37 msgid "Payment source" msgstr "Maksutapa" -#: .\members\templates\member_add_many.html:37 +#: .\members\templates\member_add_many.html:41 msgid "Cash payment" msgstr "Käteismaksu" -#: .\members\templates\member_add_many.html:41 +#: .\members\templates\member_add_many.html:44 +msgid "" +"This payment source will be used to create any payments for new members that " +"already exist in the database." +msgstr "" +"Tätä maksutapaa käytetään, kun jo tietokannassa oleville jäsenille luodaan " +"maksutapahtuma." + +#: .\members\templates\member_add_many.html:48 msgid "CSV delimiter" msgstr "CSV-erotin" -#: .\members\templates\member_add_many.html:44 +#: .\members\templates\member_add_many.html:51 msgid "" "The symbol that is used to separate items in one line. Defaults to " "';' (semicolon)." @@ -470,11 +478,11 @@ msgstr "Maksutapahtumia:" msgid "Language" msgstr "Kieli" -#: .\members\templates\settings.html:20 .\sikweb\base.py:222 +#: .\members\templates\settings.html:20 .\sikweb\base.py:226 msgid "Finnish" msgstr "suomi" -#: .\members\templates\settings.html:21 .\sikweb\base.py:223 +#: .\members\templates\settings.html:21 .\sikweb\base.py:227 msgid "English" msgstr "englanti" @@ -561,9 +569,9 @@ msgstr "Onnistuneesti päivitettiin maksutapahtuma" msgid "Could not update payment object" msgstr "Maksutapahtumaobjektia ei voitu päivittää" -#: .\members\views\utils.py:117 -msgid "Missing \"textfield\" POST request field" -msgstr "Puuttuva \"textfield\" POST-kenttä" +#: .\members\views\utils.py:121 +msgid "Missing CSV file" +msgstr "Puuttuva CSV-tiedosto" #: .\templates\admin\base_site.html:43 msgid "Go" @@ -577,7 +585,7 @@ msgstr "Virhe" msgid "Back" msgstr "Takaisin" -#: .\templates\footer.html:23 +#: .\templates\footer.html:23 .\webapp\templates\kaehmy_footer.html:23 msgid "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" msgstr "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" @@ -831,7 +839,7 @@ msgstr "Telegram-kanavat" msgid "SIK Admin" msgstr "SIK Hallintapaneeli" -#: .\webapp\templates\base.html:15 +#: .\webapp\templates\base.html:15 .\webapp\templates\kaehmy_base.html:14 msgid "Aalto-yliopiston Sähköinsinöörikilta ry" msgstr "Aalto-yliopiston Sähköinsinöörikilta ry" @@ -1023,5 +1031,28 @@ msgstr "Kaikki haasteet" msgid "Total challenges:" msgstr "Haasteita yhteensä:" +#~ msgid "" +#~ "\n" +#~ " first_name, last_name, email_address and place_of_origin " +#~ "should be given string values.\n" +#~ " ayy_member and jas_recipient should be given the value 0 " +#~ "(off) or 1 (on).\n" +#~ " " +#~ msgstr "" +#~ "\n" +#~ " first_name, last_name, email_address ja place_of_origin ovat " +#~ "merkkijonoja.\n" +#~ " ayy_member ja jas_recipient ovat joko 0 (off) tai 1 (on).\n" +#~ " " + +#~ msgid "Syntax" +#~ msgstr "Syntaksi" + +#~ msgid "Data" +#~ msgstr "Data" + +#~ msgid "Missing \"textfield\" POST request field" +#~ msgstr "Puuttuva \"textfield\" POST-kenttä" + #~ msgid "Applied for board" #~ msgstr "Hakenut hallitukseen" diff --git a/members/forms.py b/members/forms.py index a0d6bd5..a946b2c 100644 --- a/members/forms.py +++ b/members/forms.py @@ -46,7 +46,7 @@ class MemberForm(forms.ModelForm): @staticmethod def csv_to_models(data, payment_source='AYY', delimiter=','): clean_data = data.strip().split('\n') - clean_data = [row.rstrip(',') for row in clean_data] + clean_data = [row.rstrip(',').rstrip('\r').strip() for row in clean_data] csv_reader = csv.DictReader(clean_data, fieldnames=MemberForm.Meta.fields, delimiter=delimiter, quoting=csv.QUOTE_NONE) members = [] @@ -122,3 +122,7 @@ class ApplicationForm(forms.ModelForm): self.fields['AYY'].label = _("I'm a member of AYY") self.fields['jas'].label = _("I want to receive a weekly newsletter") + + +class UploadFileForm(forms.Form): + file = forms.FileField() diff --git a/members/resources.py b/members/resources.py new file mode 100644 index 0000000..507b1d4 --- /dev/null +++ b/members/resources.py @@ -0,0 +1,26 @@ +from import_export import resources + +from .models import Member, Payment, Request + + +class MemberResource(resources.ModelResource): + class Meta: + model = Member + exclude = ['id', 'created'] + + +class PaymentResource(resources.ModelResource): + member = resources.Field() + + class Meta: + model = Payment + exclude = ['id'] + + def dehydrate_member(self, payment): + return '{} {}'.format(payment.member.first_name, payment.member.last_name) + + +class ApplicationResource(resources.ModelResource): + class Meta: + model = Request + exclude = ['id'] diff --git a/members/static/img/excel_csv_save_example.PNG b/members/static/img/excel_csv_save_example.PNG new file mode 100644 index 0000000..b6a78f6 Binary files /dev/null and b/members/static/img/excel_csv_save_example.PNG differ diff --git a/members/static/img/excel_csv_save_tutorial.PNG b/members/static/img/excel_csv_save_tutorial.PNG new file mode 100644 index 0000000..1cc0232 Binary files /dev/null and b/members/static/img/excel_csv_save_tutorial.PNG differ diff --git a/members/templates/application_list.html b/members/templates/application_list.html index 0fee6ad..ae22bcf 100644 --- a/members/templates/application_list.html +++ b/members/templates/application_list.html @@ -15,6 +15,10 @@ {% endif %} {{ table|safe }} + +
+ {% trans "Download Excel" %} +
{% endblock content %} diff --git a/members/templates/member_add_many.html b/members/templates/member_add_many.html index 148b1b4..15a2c85 100644 --- a/members/templates/member_add_many.html +++ b/members/templates/member_add_many.html @@ -1,7 +1,7 @@ {% extends "members_base.html" %} {% load i18n %} - +{% load static %} {% block content %}
@@ -11,24 +11,28 @@

{% blocktrans %} - Enter member information in CSV format, separate members on separate lines. + Enter member information in CSV format, separate members on separate lines. + If a new member already exists in the database, a new payment event will be created for that member instead. {% endblocktrans %}

-

- {% blocktrans %} - first_name, last_name, email_address and place_of_origin should be given string values. - ayy_member and jas_recipient should be given the value 0 (off) or 1 (on). - {% endblocktrans %} -

-

{% trans "Syntax" %}

-
first_name, last_name, email_address, place_of_origin, ayy_member, jas_recipient
-
-
{% csrf_token %} -
- - + +
+ +
+
+

{% blocktrans %}Columns: First name, last name, email address, place of origin, AYY member, JAS recipient{% endblocktrans %}

+
+
+ +
+
+ + {% csrf_token %} +

{% trans "Upload file" %}

+ +
+ + {% trans "This payment source will be used to create any payments for new members that already exist in the database." %} +
-

+ {% blocktrans %}The symbol that is used to separate items in one line. Defaults to ';' (semicolon).{% endblocktrans %} -

+
diff --git a/members/templates/member_edit.html b/members/templates/member_edit.html index 4f2c7ea..c8ef05c 100644 --- a/members/templates/member_edit.html +++ b/members/templates/member_edit.html @@ -1,7 +1,7 @@ {% extends "members_base.html" %} {% load i18n %} -{% load bootstrap3 %} +{% load bootstrap4 %} {% block content %}
diff --git a/members/templates/member_list.html b/members/templates/member_list.html index 9c0eb80..2dc38f8 100644 --- a/members/templates/member_list.html +++ b/members/templates/member_list.html @@ -41,7 +41,7 @@ {{ table|safe }}
{% endblock content %} diff --git a/members/templates/payment_list.html b/members/templates/payment_list.html index 1665f0a..bce2421 100644 --- a/members/templates/payment_list.html +++ b/members/templates/payment_list.html @@ -36,5 +36,9 @@ {% endif %} {{ table|safe }} + +
{% endblock content %} diff --git a/members/templates/upload_form.html b/members/templates/upload_form.html new file mode 100644 index 0000000..b028b1d --- /dev/null +++ b/members/templates/upload_form.html @@ -0,0 +1,10 @@ +{% extends "members_base.html" %} + +{% block content %} +

{{ title }}

+

{{ header }}

+{% csrf_token %} + {{ form }} + + +{% endblock %} \ No newline at end of file diff --git a/members/urls.py b/members/urls.py index 4988f5d..707571e 100644 --- a/members/urls.py +++ b/members/urls.py @@ -7,7 +7,7 @@ from django.views.generic.base import RedirectView # members from members.views import member_list, payment_add, payment_submit from members.views import application_delete_confirm, application_delete -from members.views import application_accept, import_csv, export_csv +from members.views import application_accept, import_csv from members.views import settings_page, payment_edit from members.views import payment_delete_confirm from members.views import payment_delete, payment_update @@ -20,6 +20,9 @@ from members.views import member_delete_confirm from members.views import member_delete from members.views import payment_list from members.views import add_many_confirm +from members.views import export_members_excel +from members.views import export_payments_excel +from members.views import export_applications_excel # autocomplete view from members.views import MemberAutoComplete @@ -108,8 +111,10 @@ urlpatterns = [ # send CSV member data by POST url(r'^import_csv', import_csv), - # download CSV member data - url(r'^export_csv', export_csv), + # export members as excel file + url(r'export_members', export_members_excel), + url(r'export_payments', export_payments_excel), + url(r'export_applications', export_applications_excel), # favourite icon url(r'^favicon\.ico$', favicon_view), diff --git a/members/views/utils.py b/members/views/utils.py index 83727a6..6223cba 100644 --- a/members/views/utils.py +++ b/members/views/utils.py @@ -2,7 +2,7 @@ from django.shortcuts import render from django.contrib.auth.decorators import permission_required, login_required from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest from django.core.mail import send_mail from django.conf import settings from django.utils.translation import ugettext as _ @@ -20,8 +20,9 @@ from rest_framework import generics from rest_framework import permissions from members.models import Member, Request, Payment -from members.forms import MemberForm, PaymentForm, ApplicationForm, CSVValidationError +from members.forms import MemberForm, PaymentForm, ApplicationForm, CSVValidationError, UploadFileForm from members.tables import MemberTable, PaymentTable, RequestTable +from members.resources import MemberResource, PaymentResource, ApplicationResource # Can be used to retrieve single member information via REST API @@ -108,13 +109,16 @@ def settings_page(request, *args, **kwargs): def import_csv(request, *args, **kwargs): """Get csv data imported to page and create members based on that.""" try: - data = request.POST['textfield'] + csv_in_memory_file = request.FILES.get('csvFile') + csv_file = csv_in_memory_file.file + data = csv_file.read().decode('utf-8') + delimiter = request.POST.get('delimiter', ',') payment_source = request.POST['payment_source'] except: return render(request, 'error.html', - {'error': _('Missing "textfield" POST request field')}) + {'error': _('Missing CSV file')}) try: result = MemberForm.csv_to_models(data, payment_source=payment_source, delimiter=delimiter) @@ -149,27 +153,6 @@ def import_csv(request, *args, **kwargs): return render(request, 'member_add_many_confirm.html', context) -@ensure_csrf_cookie -@require_http_methods(["GET"]) -@permission_required('members.read_member', login_url='/login', raise_exception=True) -def export_csv(request, *args, **kwargs): - """Export members as csv.""" - response = HttpResponse() - response['Content-type'] = 'text/csv' - response['Accept'] = 'text/csv' - response['Content-Disposition'] = 'filename; filename=members.csv' - writer = csv.writer(response, csv.excel) - # BOM (optional...Excel needs it to open UTF-8 file properly) - response.write(u'\ufeff'.encode('utf8')) - for obj in Member.objects.all(): - data = obj.as_array() - field_list = list(map(lambda d: str(d), data)) - - writer.writerow(field_list) - - return response - - def send_mail_wrapper(subject, message, email_to): """Send mail to default email.""" send_mail(subject, @@ -177,3 +160,26 @@ def send_mail_wrapper(subject, message, email_to): settings.DEFAULT_EMAIL_FROM, [email_to], fail_silently=False) + + +def make_excel_response(Resource): + res = Resource() + dataset = res.export() + response = HttpResponse(dataset.xlsx, content_type='application/vnd.ms-excel; charset=utf-8') + response['Content-Disposition'] = 'attachment; filename="export.xlsx"' + return response + + +@require_http_methods(['GET']) +def export_members_excel(request, *args, **kwargs): + return make_excel_response(MemberResource) + + +@require_http_methods(['GET']) +def export_payments_excel(request, *args, **kwargs): + return make_excel_response(PaymentResource) + + +@require_http_methods(['GET']) +def export_applications_excel(request, *args, **kwargs): + return make_excel_response(ApplicationResource) diff --git a/requirements.txt b/requirements.txt index bc58902..925b4f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,3 +30,5 @@ django-autocomplete-light==3.2.10 six==1.10.0 django-suit==0.2.25 telepot==12.3 +django-excel==0.0.9 +pyexcel-xls==0.5.2 \ No newline at end of file diff --git a/sikweb/base.py b/sikweb/base.py index c094344..b761136 100644 --- a/sikweb/base.py +++ b/sikweb/base.py @@ -82,11 +82,15 @@ INSTALLED_APPS = [ 'rest_framework', 'django_nose', 'bootstrap3', + 'bootstrap4', 'django_tables2', 'auditlog', 'phonenumber_field', + 'import_export', ] +IMPORT_EXPORT_USE_TRANSACTIONS = True + TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' NOSE_ARGS = [ @@ -255,6 +259,10 @@ MEDIA_URL = '/media/' LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/admin' +# for django-excel +FILE_UPLOAD_HANDLERS = ("django_excel.ExcelMemoryFileUploadHandler", + "django_excel.TemporaryExcelFileUploadHandler") + SUIT_CONFIG = { # header 'ADMIN_NAME': 'SIK Admin',