From 56668257388afc566ccf1dadce64d680dbc9283a Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Mon, 2 Oct 2017 20:56:49 +0300 Subject: [PATCH] Add option to choose delimiter in CSV import --- locale/en/LC_MESSAGES/django.mo | Bin 7141 -> 7141 bytes locale/en/LC_MESSAGES/django.po | 16 +++++++++++++--- locale/fi/LC_MESSAGES/django.mo | Bin 9164 -> 9462 bytes locale/fi/LC_MESSAGES/django.po | 20 ++++++++++++++++---- members/forms.py | 13 +++++++++---- members/templates/member_add_many.html | 7 +++++++ members/views/utils.py | 3 ++- 7 files changed, 47 insertions(+), 12 deletions(-) diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo index d8f27f1f729b2be1c6e91aa16e5397264ad96bbf..cc3f55d59e06919a5888c8833c4fa5badaa85100 100644 GIT binary patch delta 24 fcmaEA{?vTKO(AYW16>0n1tSA1Q=`pKgcvyiaBT;r delta 24 fcmaEA{?vTKO(AXrOI;%i1tViC6NAl9gcvyiaZU%d diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index afde5f3..7978039 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-09-28 23:40+0300\n" +"POT-Creation-Date: 2017-10-02 20:52+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -198,7 +198,7 @@ msgstr "English" msgid "Submit" msgstr "Submitted" -#: members/forms.py:110 members/tables.py:32 +#: members/forms.py:115 members/tables.py:32 msgid "Member" msgstr "Member" @@ -347,6 +347,16 @@ msgid "Cash payment" msgstr "List payments" #: members/templates/member_add_many.html:41 +msgid "CSV delimiter" +msgstr "" + +#: members/templates/member_add_many.html:44 +msgid "" +"The symbol that is used to separate items in one line. Defaults to " +"';' (semicolon)." +msgstr "" + +#: members/templates/member_add_many.html:48 #: members/templates/member_add_many_confirm.html:22 msgid "Send" msgstr "Send" @@ -526,7 +536,7 @@ msgstr "Successfully updated payment" msgid "Could not update payment object" msgstr "Could not update payment object" -#: members/views/utils.py:115 +#: members/views/utils.py:116 msgid "Missing \"textfield\" POST request field" msgstr "Missing \"textfield\" POST request field" diff --git a/locale/fi/LC_MESSAGES/django.mo b/locale/fi/LC_MESSAGES/django.mo index 619b7a6c5afeee5ad383b6e7b3e3d7d02d7ccd5f..fbdf6e5c62b6ec4962fe2ee3f87e0b7c6167c088 100644 GIT binary patch delta 3754 zcmZwJdr*{B7{~FWfQn|28s1V~6$K3tNXj&br$ zYg##K+GK?_&ZJXjNt3BvXr>!!&N$X&W;&IVGuijIdzkv8Gdz6GIq%u`ob$ZrUHD|g zAEP4Qw~1eGDBFpf6bZ(hk}df~+0fb;7dK)ZUc(kxcYVxHF^=}vcr!L&GfYg1^(SL8 z?RKbJ_QdNj2U{5vF$GlkF{5G~W-@XQFH~ggy`Bz6$TVrm-PN<1;FavK#rEofGA?2u*SE3GG#P%;n zO<0Zk{3_JA8taQlvdmso#txzG`*BX6=ljYFeY7Z8y|2 z&qaN14Dw@&YA~1dd2oDElOdcwF7E=I`U(3 z_@x~UN3v>)Q1_W>`-7+rRiSpg0=1w`sQW~=QBkUPTi>(;4x)B`7`4)mZ2xK0glADV zxP;2gRn+(-wx>s$f@*g|-9H2M%=1v0E5@FB|ASN_#v4!6MV^nm*dVAqpRH{y+PV)sUZDP!C zIE(gFmcIu-L_M1FPOOGIR*F@S~{lC#(%p@Beu!n(!*>877hjt@I|; zVarCPco1r*h1d^Ea3F3#O;nFceFN$~Kic+H)FWs{TJ`9XQ5)`pdV@@wz0e=?X%Djl zs!-pAi_pQHn2L3nj^{89llVT(#D1vjKGcF1q9$C1+Ifxb--&uO`?`>S?Qp-n@BwON z$F23Km4AzRzt5sl`7as0n)^FOazfwUCjh&)D{2FOTK~4!6G)2|*b24tPS(^26-|(a zTKQn)$Bg5b4pRs@cP5Nl*mB#y5w(-8w!I6rfxV~&y=^^+%E0@mj2%NQqycrm$ayN7 z_%A!4xf8q45qYIeI_eP>pmsJEbqI@5{Vo<@C2FEt)ItuT#@C_V`xB_0Uqo&AcjR0~ zOk1vYr=u@wMTMxHO|#BH-Pl7-xWM+WwCx(yf_9-ke*pD}j-nRwxxLof zFqQeuB`SH?hF%tBhM|MAFaxWRA?6M2gY~FKb`5pI>(XKq+=!a63#vaCHEsYZ6C-du z7NXvcmofVH{{R)G_FdG#lc+=V4eB*HjZN_~HbIpsM0vCpOM5)^v9{gFP%4i$Ht-%> zueL7K^Y3dLN~MZczJ};c+($GPrS?Ihl(>_~C6*H^&k<{h6@*9R5GvY?$_s=Jb2Phn zJE4qs*Yj7YBJ>RZuWX=m2~k8igvuCVLbMk9CiGKxiS@Rx1cSCd2P=pth*boC&&)H# zV?=cRIJ}$4PzR-FjOZb{)z-sS{adz-&_Ucx@cj~f#$alQeBur@C?R4bq1R1C@Bfp; zYC`2HBD#MahQ_j}v4W$BX~g4%4$dS(WoZm^KW-vM5DyU#5EBWNAu*zV342gqKs-Y5 zH!fQAMm((fGpXp*&L^HGl8G`xMTc)2F^(8O@E13F5FvU%Z^L`lu%#acY<)V;BSsS& z34QAo5OazCMC{4)dk~FYgx&y^8AN+xIMIhtsU&6*&l6jT*~GI%W0_24C2?0{2Nn`D z|I?mI-A61YQi*J0piXKUv4v1sM`T57|Nh!ewV1et7+jm*dVbTEMH8JFZopsW_iFbf zmB%HF@drF#ZO69tafP#8Cp^DwdMMy{vwfc94?C4%cZTDIoUmK&tMGZQGbiNvoYEsZ=6kMpWXF*mL8rn$ uS96B_ZqU&uJztqW?7G2hXI#MbDoev|&=;G$yfPH%k1-d6#oMqS$7Tq delta 3462 zcmYk-3rv+|9LMoT4x*-b0Z}xFqr&lms2wl?Z)kYUJ4TwBS)i48L)7s0T2YoM<^{^o zrDmHsP3JM~YRhGYUFM>eD~p;f=ccusv`Oar{?7TkeCChO^E~f+-skdO{Cmuoqr9Kv zqN^NbCrKjFO`WU5%Psgr$&Pid7<2G6zK+dtZtIAP&_}x*({VM%;9J&z7~9f5ig(~C zY=vjBrE{M9iAozfE=4-rb>yFGN~eC<9`%DX?2SRpz*!iL8<9D=EvWN$S^q(6A3?3< zV@$?cY=#%HKjXVU?SwQ&>&Ah;W&z$sdpV|HwY85~`#bDJe*Vbp-{S^p>I zY1EE>h1!Yps9W?qdOC20iUzoWi5MFf890Eta5`$BEYtwGs1*;l8R_@ zvi1Vh`DNGzJ!|idWB(KAI6#L6I*C2-3)B`~L+wCRd}QX$P!C%>RDS~Mcb)BcH!}lS ziyMI2sWGVQ6{1#Ngj&eFc=lf_Ut%Xz*a=&Ze{MT}cs$%e)V=-)^~3M6J=RbN zpF(}{YEc6;peB41b$(3ehzVvY>i3zbTQ>~b>HVKdMGx5=)YdLTt#CbNVGRz%v#5bu zv2WV)1k{E6s4dS#-KxQ;m5xPSZ?g3lV}IJEc6=Xt`r;j;;>S8n!E4wZ+jC!1aS-;# z*{I`{sENFd8t^!3#h+S#9cqiuqZan7_5X#MSfkk_nf=$yoAY7Tha(QPg^8$p=r@C? z0rF7;79bD0djvI+rKsPpL0zu`wKJ8dE#HmWu|w8=AGI@|C$s<5-Fg0K;6~IZHi{3w z+O1I+?qKaC)Cy9~bUPkIO)wj^@=@kE)b%H$CcY50gR4-_&<>9Z&zswYn(4cC;4{=p z&RF|f)C$g_CUgO{@=K_lx{8`WG*{Pk;!y*3K^^a7{dve6=q8|UjaNiPD=I@hbSv$^ z1{_R#2Wp@nP!qU-I{y#U``v(AaYuh-rAf%+<8rYp7NRCpj#|(()DQO{53D4pEG?pc7V=z^K30S2K4%(wn&sPkr{c47hQZ74@guoAVSRd)PM)Q%iRy%onW3Tx48 zLPbUQdNO&8JV{h^v3#Q0PA9#|^W-I>(uWii?Vie7GJ$L+1*D1$CweedbQ^1k7F|Lp zUigco+Ek)#A4Ie&Jyf@s(KJSoDP$d)NmTA5Y+SfJ#NX%0axygBKe}baHVMxmENQm69h&_eiJb zc2G$r8zLRySEbPES@(psf;8EqyOAtOb&bVwq!(FWeJ)fLTOJikYFpw9RmRu(w!YJG lQ_Fri8NqCSFf%u+Uua_D0beL4>4-0MB4u0j);CfM{sY|WBNhMv diff --git a/locale/fi/LC_MESSAGES/django.po b/locale/fi/LC_MESSAGES/django.po index 758ca35..df65fb7 100644 --- a/locale/fi/LC_MESSAGES/django.po +++ b/locale/fi/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-09-28 23:40+0300\n" +"POT-Creation-Date: 2017-10-02 20:52+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -197,7 +197,7 @@ msgstr "englanti" msgid "Submit" msgstr "Lisää" -#: members/forms.py:110 members/tables.py:32 +#: members/forms.py:115 members/tables.py:32 msgid "Member" msgstr "Jäsen" @@ -343,6 +343,18 @@ msgid "Cash payment" msgstr "Käteismaksu" #: members/templates/member_add_many.html:41 +msgid "CSV delimiter" +msgstr "CSV-erotin" + +#: members/templates/member_add_many.html:44 +msgid "" +"The symbol that is used to separate items in one line. Defaults to " +"';' (semicolon)." +msgstr "" +"Merkki, jota käytetään rivin osien erottamiseen. Oletuksena " +"';' (puolipiste)." + +#: members/templates/member_add_many.html:48 #: members/templates/member_add_many_confirm.html:22 msgid "Send" msgstr "Lähetä" @@ -518,7 +530,7 @@ msgstr "Onnistuneesti päivitettiin maksutapahtuma" msgid "Could not update payment object" msgstr "Maksutapahtumaobjektia ei voitu päivittää" -#: members/views/utils.py:115 +#: members/views/utils.py:116 msgid "Missing \"textfield\" POST request field" msgstr "Puuttuva \"textfield\" POST-kenttä" @@ -640,7 +652,7 @@ msgstr "Fuksit" #: webapp/templates/guild.html:7 msgid "Kilta" -msgstr "" +msgstr "Kilta" #: webapp/templates/international.html:7 webapp/templates/navigation.html:30 msgid "International" diff --git a/members/forms.py b/members/forms.py index 0cd4a8c..9a573ee 100644 --- a/members/forms.py +++ b/members/forms.py @@ -52,16 +52,21 @@ class MemberForm(forms.ModelForm): return self._clean_boolean_field('AYY') @staticmethod - def csv_to_models(data, payment_source='AYY'): + def csv_to_models(data, payment_source='AYY', delimiter=','): clean_data = data.strip().split('\n') clean_data = [row.rstrip(',') for row in clean_data] - csv_reader = csv.DictReader(clean_data, fieldnames=MemberForm.Meta.fields) + csv_reader = csv.DictReader(clean_data, fieldnames=MemberForm.Meta.fields, delimiter=delimiter, quoting=csv.QUOTE_NONE) members = [] payments = [] for line in csv_reader: - for key, value in line.items(): - line[key] = value.strip() + try: + for key, value in line.items(): + line[key] = value.strip() + except AttributeError as ex: + logging.error('Invalid line in CSV: "{}"'.format(line)) + logging.error('Delimiter: {}'.format(delimiter)) + raise email = line['email'] member_exists = False diff --git a/members/templates/member_add_many.html b/members/templates/member_add_many.html index 9d9b4e8..148b1b4 100644 --- a/members/templates/member_add_many.html +++ b/members/templates/member_add_many.html @@ -37,6 +37,13 @@ +
+ + +

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

+
diff --git a/members/views/utils.py b/members/views/utils.py index 02ac5d2..89839c8 100644 --- a/members/views/utils.py +++ b/members/views/utils.py @@ -108,6 +108,7 @@ def import_csv(request, *args, **kwargs): """Get csv data imported to page and create members based on that.""" try: data = request.POST['textfield'] + delimiter = request.POST.get('delimiter', ',') payment_source = request.POST['payment_source'] except: return render(request, @@ -115,7 +116,7 @@ def import_csv(request, *args, **kwargs): {'error': _('Missing "textfield" POST request field')}) try: - result = MemberForm.csv_to_models(data, payment_source=payment_source) + result = MemberForm.csv_to_models(data, payment_source=payment_source, delimiter=delimiter) except CSVValidationError as ex: logging.exception('Model validation error') return error_view(request, ex.form_errors)