From 470c75a4796d88c92b9716deccfc37917d1c04c4 Mon Sep 17 00:00:00 2001 From: Koichi Harakawa Date: Thu, 19 Sep 2013 12:40:57 +0900 Subject: [PATCH 001/119] Add Japanese translation. --- avatar/locale/ja/LC_MESSAGES/django.mo | Bin 0 -> 3430 bytes avatar/locale/ja/LC_MESSAGES/django.po | 131 +++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 avatar/locale/ja/LC_MESSAGES/django.mo create mode 100644 avatar/locale/ja/LC_MESSAGES/django.po diff --git a/avatar/locale/ja/LC_MESSAGES/django.mo b/avatar/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..1a836fff0c7dfdf545f69e64f82f42b3c4cf7fb7 GIT binary patch literal 3430 zcmb`JNo*Tc7{?#96l&I%^#JHm2*kAGIKUxslTeemZPYjkSz4tMSQGoj9+=F8S&|0z zkg+SJOK1>uQ5Vq`s+LlkAVek9jRRMX91#Kyc3LjL9SQ#LjmHjgoTd_^jDMcz?|u9C zCO@xTd6?jO0{7Fnf580=?%j9c1J|Em0{jc?2j9G#5FI=Zt^%K2LCC$}v*23rMerf8 z5qtpL3O0cK;Ck>N_#Aizd>;G>d;}yb3E2Ux0S7<@jDg>S5peZAuno3>kAp|RF7Qi` z`|&q803TQ2VG7T0!Kt^w-@%h$`+bBw1r|Uq{}0IhShbpvm%&<)ulIs6a3}aWcp40Y zzZBQk1PFNn&pW_La5tC*SKjaWJqap!{uNAu+mHkxe+0Q7@dpWkyCO$CZ)RTm~N{n zsw(d?YUwm3c85r>orF1a$X3_Os>>;^K!o9` z36cI0zDzq2S^Kb@W@G@)$trpyHI6)vGL%CbOcbpKOZGRQx}Iyp@-AiA9>ykBAA^1r zUTnd7d0R;675X&Yk6~Wqw3xEW0wpuDmS%pzZO>g@W1`TSJ~mJDB1xc?3aeC{$IboI zUa~L@ey%is6vmkq@|`R@L461Oq>I)YWK8o1DnyYDFMF7d?F=%nliXKELPod#W z5^`+mIvrHfw6>I9~Rk-q^+(0baBgMO#eHmhg z6w{J=O3~60+AyeCfo|0{WL4U%8^dOVY9r#&Y_8u(y|2yTjr=V1Qatahb)Ca*_G8zX za&t%B+$A@M$Isl{H8*#0?$FhIZhBt3P&fOLoBhwMuldkP26jPzWuk3oh2TM zb#nGp6EB$%lIL7!+I3Fz^kB3?5XNaxLS(@SK*`+uXV z%_?PD{(Eha!0#}`%E~R?s&^cNe>~p7i*auHM*bvDu9<4a{ymPSqopIwA6o9hmHITqt1b) literal 0 HcmV?d00001 diff --git a/avatar/locale/ja/LC_MESSAGES/django.po b/avatar/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..c417e51 --- /dev/null +++ b/avatar/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,131 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-09-18 19:49+0900\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: admin.py:19 +msgid "Avatar" +msgstr "プロフィール画像" + +#: forms.py:24 +msgid "avatar" +msgstr "プロフィール画像" + +#: forms.py:37 +#, python-format +msgid "" +"%(ext)s is an invalid file extension. Authorized extensions are : %" +"(valid_exts_list)s" +msgstr "%(ext)s は利用できない拡張子です。 使用可能な拡張子 : %(valid_exts_list)s" + +#: forms.py:44 +#, python-format +msgid "" +"Your file is too big (%(size)s), the maximum allowed size is %" +"(max_valid_size)s" +msgstr "ファイルが大きすぎます(%(size)s)。アップロード可能な最大サイズは %(max_valid_size)s です。" + +#: forms.py:54 +#, python-format +msgid "" +"You already have %(nb_avatars)d avatars, and the maximum allowed is %" +"(nb_max_avatars)d." +msgstr "登録可能なプロフィール画像は %(nb_max_avatars)d 個までです。すでに %(nb_avatars)d 個登録されています。" + +#: forms.py:71 forms.py:84 +msgid "Choices" +msgstr "選択" + +#: views.py:74 +msgid "Successfully uploaded a new avatar." +msgstr "新しいプロフィール画像をアップロードしました。" + +#: views.py:110 +msgid "Successfully updated your avatar." +msgstr "プロフィール画像を更新しました。" + +#: views.py:148 +msgid "Successfully deleted the requested avatars." +msgstr "指定されたプロフィール画像を削除しました。" + +#: templates/avatar/add.html:6 templates/avatar/change.html:6 +msgid "Your current avatar: " +msgstr "現在のプロフィール画像:" + +#: templates/avatar/add.html:9 templates/avatar/change.html:9 +msgid "You haven't uploaded an avatar yet. Please upload one now." +msgstr "登録されているプロフィール画像はありません。アップロードしてください。" + +#: templates/avatar/add.html:13 templates/avatar/change.html:20 +msgid "Upload New Image" +msgstr "新しい画像のアップロード" + +#: templates/avatar/change.html:15 +msgid "Choose new Default" +msgstr "デフォルトの画像を選択" + +#: templates/avatar/confirm_delete.html:6 +msgid "Please select the avatars that you would like to delete." +msgstr "削除したいプロフィール画像を選択してください。" + +#: templates/avatar/confirm_delete.html:9 +#, python-format +msgid "" +"You have no avatars to delete. Please upload one now." +msgstr "削除できるプロフィール画像はありません。新規画像のアップロード." + +#: templates/avatar/confirm_delete.html:15 +msgid "Delete These" +msgstr "削除" + +#: templates/notification/avatar_friend_updated/full.txt:1 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "%(avatar_creator)s さんがプロフィール画像 %(avatar)s をアップロードしました。\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_friend_updated/notice.html:2 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s." +msgstr "%(avatar_creator)s さんがプロフィール画像 %(avatar)s をアップロードしました。" + +#: templates/notification/avatar_updated/full.txt:1 +#, python-format +msgid "" +"Your avatar has been updated. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "プロフィール画像を更新しました。 %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_updated/notice.html:2 +#, python-format +msgid "You have updated your avatar %(avatar)s." +msgstr "プロフィール画像を更新しました。 %(avatar)s." + +#: templatetags/avatar_tags.py:51 +msgid "Default Avatar" +msgstr "デフォルトのプロフィール画像" From e80d39a618228a5f4b722e83a45b8699373fe433 Mon Sep 17 00:00:00 2001 From: Ivor Bosloper Date: Mon, 11 Nov 2013 12:56:52 +0100 Subject: [PATCH 002/119] Dutch translations --- avatar/locale/nl/LC_MESSAGES/django.mo | Bin 0 -> 2942 bytes avatar/locale/nl/LC_MESSAGES/django.po | 141 +++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 avatar/locale/nl/LC_MESSAGES/django.mo create mode 100644 avatar/locale/nl/LC_MESSAGES/django.po diff --git a/avatar/locale/nl/LC_MESSAGES/django.mo b/avatar/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..c5f2142a4b23be71ea0885ad583e6fb4597634ad GIT binary patch literal 2942 zcmb`I%W@k<6oxw_Tp|dNa9ePxlTapBB{Q}hQkBS;im@HX#7RUf2eLuc)*MM=M$@9Z z$BGTF0Ic8@*sxpg1AK$G~auJ{W^b;ICj6Joz-v1{cBC!0*62;18g);~%gO8;|3m zjpr|5l+*VJ?1R(K3GqDmBk1IR0iB-T27CxQyZ;6Q@YqTC22Ox3Hp}3f;HTiL;10M3 zegj6}BXAMCQ4%5qzXEIE&!E$D3Wu+PW1zD`;|u2c7`eEe#tj$5E4ba|Y;)(h3nB8? zDSRUw{&F@!wfDu@{gPi50%`I32af_~`TV#T!!;N%F1MtWy3y1uthv#nPHtDc5ZI> z@LgwSCgj}F4vnZ8M8R7ZjKo4m#Z5Mj$}pwer$uhbEU{uh8b~g3!j`Gt zVZ)-9u!Ok5TGP6a4gzZMTUy#y8TD0`M3lszF4WMbdj}*EB_pT6yOFC2#d^;z(`|UR(v@u%_hFn&P#e)U;<&{~N4n7% zoLb&J|01%Ro7R;N;%?T(rbP9jABp!{us+-tdc9s>stO-QJf}g(4koDCk!hQYglD3NH0C}Ncst+35DEQ}l)L4^TD(0%D`FsDUBg@kD2 z(L;AUZWF;6O@lrgSWqPwLY;RKVr-S7jkrzYW8(&WR5s;{zS8!m!@bON;u4Z~R=z>x zW{H|so2b)ZB?|7bcKunU+Wf-J`Q;_Lw{&-H<<9NWUG6DugIlH@N5KbK+XQu0rBdxq zJy>va1e=0I43H{KO;#=il?pyonW|ozx-eOpoP=O-m$zc4{7|{~ujX>A(%7J`Woi;P zoT{|4r8LdN_`cTEsu$?6sk(EeRTM>rat-P%yH#49zrDQf?44O%y_UqG((Sp@t(99# zLys!qWNAUAm_RsSy9Y}x2Fye+k#Rars4{KX&aT(52Umu2&X5-CU@2{?C{Ei|y0Q`5 zQZ31}OoHo5cTJVjo_{p6Q`40HoE=Z;>?~Ev)1^;>WlmY=&eRk~v876QIlSy9WuAc1 zNzB}`v=eWp)YGaJbJ9{64_mC$n6rK~QcF)XkzHXbv{MqHayBqf(8Q(%H>5;)*A=(@ z8k1i`ta4lamzn%uu03|AqF#&0h?|`4U_RfB*^mzrrmk~JN*#%{;@4;}1!}w>Z$_*! zV0T!o`612z5hdYboxg_j5s&UXkD)tq_E0i9u%2ft#Gk~d0@sF6kB_mtlh=!)ZjgaZ z7E3yhxJ>dPI-I*B^>E%?qz+s1tuFD$DrIW1}?@>dlyU*qDkb${(0_T4i ze)>9ndC-sWG!MfeDvy}KuoOO|s!jWC4JkjDM$i24u;>m#|3qUK>FQ)LdSj2`s, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-11-11 12:32+0100\n" +"PO-Revision-Date: 2013-11-11 12:49+0100\n" +"Last-Translator: Ivor \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.5.5\n" + +#: admin.py:19 +msgid "Avatar" +msgstr "Profielfoto" + +#: forms.py:24 +msgid "avatar" +msgstr "profielfoto" + +#: forms.py:37 +#, python-format +msgid "" +"%(ext)s is an invalid file extension. Authorized extensions are : " +"%(valid_exts_list)s" +msgstr "" +"%(ext)s is een ongeldig bestandsformaat. Toegestane formaten zijn : " +"%(valid_exts_list)s" + +#: forms.py:44 +#, python-format +msgid "" +"Your file is too big (%(size)s), the maximum allowed size is " +"%(max_valid_size)s" +msgstr "" +"Het bestand is te groot (%(size)s), de maximale groote is %(max_valid_size)s" + +#: forms.py:54 +#, python-format +msgid "" +"You already have %(nb_avatars)d avatars, and the maximum allowed is " +"%(nb_max_avatars)d." +msgstr "" +"Er zijn al %(nb_avatars)d profielfoto's, het maximale aantal is " +"%(nb_max_avatars)d." + +#: forms.py:71 forms.py:84 +msgid "Choices" +msgstr "Keuzes" + +#: views.py:74 +msgid "Successfully uploaded a new avatar." +msgstr "De profielfoto is ververst." + +#: views.py:110 +msgid "Successfully updated your avatar." +msgstr "Profielfoto vernieuwd." + +#: views.py:148 +msgid "Successfully deleted the requested avatars." +msgstr "Profielfoto verwijderd." + +#: templates/avatar/add.html:6 templates/avatar/change.html:6 +msgid "Your current avatar: " +msgstr "De huidige profielfoto:" + +#: templates/avatar/add.html:9 templates/avatar/change.html:9 +msgid "You haven't uploaded an avatar yet. Please upload one now." +msgstr "Er is nog geen profielfoto. Upload een nieuwe." + +#: templates/avatar/add.html:13 templates/avatar/change.html:20 +msgid "Upload New Image" +msgstr "Upload nieuw plaatje" + +#: templates/avatar/change.html:15 +msgid "Choose new Default" +msgstr "Kies nieuwe standaard" + +#: templates/avatar/confirm_delete.html:6 +msgid "Please select the avatars that you would like to delete." +msgstr "Selecteer de te verwijderen de profielfoto's." + +#: templates/avatar/confirm_delete.html:9 +#, python-format +msgid "" +"You have no avatars to delete. Please upload one now." +msgstr "" +"Er zijn geen profielfoto's om te verwijderen. Upload een nieuwe." + +#: templates/avatar/confirm_delete.html:15 +msgid "Delete These" +msgstr "Verwijder deze" + +#: templates/notification/avatar_friend_updated/full.txt:1 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" +"%(avatar_creator)s heeft zijn profielfoto vernieuwd %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_friend_updated/notice.html:2 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s." +msgstr "" +"%(avatar_creator)s heeft zijn profielfoto " +"vernieuwd %(avatar)s." + +#: templates/notification/avatar_updated/full.txt:1 +#, python-format +msgid "" +"Your avatar has been updated. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" +"Je profielfoto is vernieuwd. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_updated/notice.html:2 +#, python-format +msgid "You have updated your avatar %(avatar)s." +msgstr "De profielfoto is vernieuwd %(avatar)s." + +#: templatetags/avatar_tags.py:51 +msgid "Default Avatar" +msgstr "Standaard profielfoto" From b7f5cb3a7fce157db5bce1456c6ff8a8b6ddf784 Mon Sep 17 00:00:00 2001 From: Roberto Date: Thu, 2 Jan 2014 13:22:56 +1100 Subject: [PATCH 003/119] Calling syncdb in the usage instructions --- docs/index.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/index.txt b/docs/index.txt index c1dda78..5e19f22 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -38,7 +38,11 @@ that are required. A minimal integration can work like this: 'avatar', ) -2. Add the avatar urls to the end of your root urlconf. Your urlconf +2. Update your database:: + + python manage.py syncdb + +3. Add the avatar urls to the end of your root urlconf. Your urlconf will look something like:: urlpatterns = patterns('', @@ -46,12 +50,12 @@ that are required. A minimal integration can work like this: (r'^avatar/', include('avatar.urls')), ) -3. Somewhere in your template navigation scheme, link to the change avatar +4. Somewhere in your template navigation scheme, link to the change avatar page:: Change your avatar -4. Wherever you want to display an avatar for a user, first load the avatar +5. Wherever you want to display an avatar for a user, first load the avatar template tags:: {% load avatar_tags %} From c1f278bb84a48c143111000f29bbd640ab52a677 Mon Sep 17 00:00:00 2001 From: Andrea de Marco <24erre@gmail.com> Date: Fri, 10 Jan 2014 10:35:07 +0100 Subject: [PATCH 004/119] Preserve RGBA image.mode --- avatar/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avatar/models.py b/avatar/models.py index 5bc3a52..0657b6c 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -103,7 +103,7 @@ class Avatar(models.Model): else: diff = int((h - w) / 2) image = image.crop((0, diff, w, h - diff)) - if image.mode != "RGB": + if image.mode not in ("RGB", "RGBA"): image = image.convert("RGB") image = image.resize((size, size), settings.AVATAR_RESIZE_METHOD) thumb = six.BytesIO() From 3b3bdd8df453d3373745e2768a6555f22630836d Mon Sep 17 00:00:00 2001 From: z4r <24erre@gmail.com> Date: Fri, 10 Jan 2014 12:16:08 +0100 Subject: [PATCH 005/119] RGBA and CMYK thumb creation tests --- tests/data/django.png | Bin 0 -> 2349 bytes tests/data/django_pony_cmyk.jpg | Bin 0 -> 11862 bytes tests/tests.py | 14 ++++++++++++++ 3 files changed, 14 insertions(+) create mode 100644 tests/data/django.png create mode 100644 tests/data/django_pony_cmyk.jpg diff --git a/tests/data/django.png b/tests/data/django.png new file mode 100644 index 0000000000000000000000000000000000000000..82474cbfde924b2a7607153ae7a1e24f4fae2ed0 GIT binary patch literal 2349 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 T62BAR00000NkvXXu0mjf@QQ0i literal 0 HcmV?d00001 diff --git a/tests/data/django_pony_cmyk.jpg b/tests/data/django_pony_cmyk.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2712f7762709de24aff22441a6f1c0eaec27f806 GIT binary patch literal 11862 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 literal 0 HcmV?d00001 diff --git a/tests/tests.py b/tests/tests.py index ee31c95..2df578a 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -2,6 +2,7 @@ import os.path from django.test import TestCase from django.core.urlresolvers import reverse +from django.test.utils import override_settings from avatar.conf import settings from avatar.util import get_primary_avatar, get_user_model @@ -126,3 +127,16 @@ class AvatarUploadTests(TestCase): # def testChangePrimaryAvatar # def testDeleteThumbnailAndRecreation # def testAutomaticThumbnailCreation + + @override_settings(AVATAR_THUMB_FORMAT='png') + def testAutomaticThumbnailCreationRGBA(self): + upload_helper(self, "django.png") + avatar = get_primary_avatar(self.user) + image = Image.open(avatar.avatar.storage.open(avatar.avatar_name(settings.AVATAR_DEFAULT_SIZE), 'rb')) + self.assertEqual(image.mode, 'RGBA') + + def testAutomaticThumbnailCreationCMYK(self): + upload_helper(self, "django_pony_cmyk.jpg") + avatar = get_primary_avatar(self.user) + image = Image.open(avatar.avatar.storage.open(avatar.avatar_name(settings.AVATAR_DEFAULT_SIZE), 'rb')) + self.assertEqual(image.mode, 'RGB') From 8ff6f08a497adba17bd02eae9ec6425a71927e08 Mon Sep 17 00:00:00 2001 From: allenling <328703810@qq.com> Date: Tue, 14 Jan 2014 08:48:48 +0800 Subject: [PATCH 006/119] Update admin.py The problem is that always display primary avatar for User. In admin page, the function get_avatar should return different avatar url for every avatar record --- avatar/admin.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/avatar/admin.py b/avatar/admin.py index 7d3151e..ffaa019 100644 --- a/avatar/admin.py +++ b/avatar/admin.py @@ -1,9 +1,10 @@ from django.contrib import admin from django.utils.translation import ugettext_lazy as _ +from django.utils import six +from django.template.loader import render_to_string from avatar.models import Avatar from avatar.signals import avatar_updated -from avatar.templatetags.avatar_tags import avatar from avatar.util import get_user_model @@ -14,7 +15,13 @@ class AvatarAdmin(admin.ModelAdmin): list_per_page = 50 def get_avatar(self, avatar_in): - return avatar(avatar_in.user, 80) + context = dict({ + 'user': avatar_in.user, + 'url': avatar_in.avatar.url, + 'alt': six.text_type(avatar_in.user), + 'size': 80, + }) + return render_to_string('avatar/avatar_tag.html',context) get_avatar.short_description = _('Avatar') get_avatar.allow_tags = True From bae78c0e95d28e0fa7c3dce801736bb09d991870 Mon Sep 17 00:00:00 2001 From: Andrew Barrett Date: Mon, 24 Feb 2014 15:23:23 +0000 Subject: [PATCH 007/119] Django allows @ for usernames, so the render_primary url pattern should do so also. --- avatar/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avatar/urls.py b/avatar/urls.py index 171cd0c..3c6bec8 100644 --- a/avatar/urls.py +++ b/avatar/urls.py @@ -8,7 +8,7 @@ urlpatterns = patterns('avatar.views', url(r'^add/$', 'add', name='avatar_add'), url(r'^change/$', 'change', name='avatar_change'), url(r'^delete/$', 'delete', name='avatar_delete'), - url(r'^render_primary/(?P[\w\d\.\-_]{3,30})/(?P[\d]+)/$', 'render_primary', name='avatar_render_primary'), + url(r'^render_primary/(?P[\w\d\@\.\-_]{3,30})/(?P[\d]+)/$', 'render_primary', name='avatar_render_primary'), url(r'^list/(?P[\+\w\@\.]+)/$', 'avatar_gallery', name='avatar_gallery'), url(r'^list/(?P[\+\w\@\.]+)/(?P[\d]+)/$', 'avatar', name='avatar'), ) From 75394c296201121889bb7643358a3183fc8c0b5e Mon Sep 17 00:00:00 2001 From: ayang23 Date: Wed, 26 Mar 2014 17:28:03 +0800 Subject: [PATCH 008/119] added simple chinese translation --- avatar/locale/zh_CN/LC_MESSAGES/django.mo | Bin 0 -> 2842 bytes avatar/locale/zh_CN/LC_MESSAGES/django.po | 135 ++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 avatar/locale/zh_CN/LC_MESSAGES/django.mo create mode 100644 avatar/locale/zh_CN/LC_MESSAGES/django.po diff --git a/avatar/locale/zh_CN/LC_MESSAGES/django.mo b/avatar/locale/zh_CN/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..6d4b7b64f3c47466d80bd03d384c91cb222c3702 GIT binary patch literal 2842 zcmb`H-)|IE6vwZEKUjYt;ExA?F12f%%KwT&iC}vZ>acW`#@I(Md} z#)pFZDhf0)kXlH9SZOiZA`+<-qKS#V_#bFY3_H8+6Z&Z4gWo%MW_O_wkvPfhXXoB? z&;6cr?mfTFpM8|zc^vOkcz?$GG~V~`!VjK5z!dl=*a5zFHz6Dx0q+H$m_^8a;4|QS z@Hy~d@I~-J@D;EL>;M;ohrwsTOW-2#SMU*#%qHXwU>>*~G{Ftv4`33Ua}V|gTfoP_ zW8fC>3sCC#8|;I|S@_t7?>!JD_5K2OfsOYoyTOnrL8mp`d<)zMt_6PwSA&aUO5fX{^m7i}1pWw0y$c>71abonGH>(nA_TGk zuYBa1M}vQeDda;S(h)qeUT_uolKGaJJ>7E%QDo>G1H;SghsY;p~qr5*DWL)8tUrPp5rjvO$pOwaS_?1JjaTQ82q!H zE}WWz8a6fUZo@J&w9B*@#RRj3$!(pk_1qkH%=fTkWfTh>Mw8ezSd+qpNLi+UH?rEG zIfr#MFRZKg1as783)fUOuLQHY!B}(afNI=?SqM~D9mR!opp&&hj>!5PH`7c=a>1z0 zdT0ylGCa#AA!%sY!Yt-8+MZ*Akv5ANFc%n0yE3I=LIwUCF74$W?ctu4p_cg$qb{eJ zV6{$O_tMx-ba|H58x95~p$>c3V?q{4=@vKGM&*O+sCqLjEN*0^gCGp$MkgHwIZR(g zWUYB4%gA*1%94h`>Fs31vY3LSNmkYkr~+G%EK zeOSPnU@lt{o( z+se94>G~#iE0c*PWw*%?uGa1twy1m!{6WfFl z4~JH3XGZ>Ctv9!B-cXIOQBTCya~mBATlN;9-9^J`C|HJRucA10j$m$cNBc&tscI*s zbumZVV5fP;w6jUt)M>i0Hp_DiOWVkuyhu{J5PXW}##L1PZBDF;y{Wy-Z04xA+BnOY zE^XA8>nml;RC%sx$))2LO2^I>FYWV(FZdrEsX0Ucy%U!P$BPq(N?(3jK0Q_*+EY5V zzc~3#ssF71)lq-o(AB=(v^p1!7AG$KFP-?tIBxqos<_E?U;p&!ZzW0}o}Hc?oEjS@ z3Za32;MDXd7z+%h&g@d(2vf}?I#N0?;2%7xCTd2546AQtQMD~j94uZwRkc;$C`ftl zNV$JMDeWFDA0PAk50y^zt7fMPD9|5^6Q8SvOK9mtpFce09~m!Bepa!(t}ROIVB7Pj zVW8G2dnH$=Q{xwJ(!;KAib`H_q7U96Qn``+F>t+m)W3MXJbC1fOMz&oz8fqB62q+~ zCyQ5(s(r3q{s, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: django-avatar\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-26 16:50+0800\n" +"PO-Revision-Date: 2014-03-26 17:08+0800\n" +"Last-Translator: Bruce Yang \n" +"Language-Team: Bruce Yang \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 1.5.7\n" + +#: admin.py:19 +msgid "Avatar" +msgstr "头像" + +#: forms.py:24 +msgid "avatar" +msgstr "头像" + +#: forms.py:37 +#, python-format +msgid "" +"%(ext)s is an invalid file extension. Authorized extensions are : " +"%(valid_exts_list)s" +msgstr "%(ext)s 是不正确的文件扩展名。 正确的扩展名为 : %(valid_exts_list)s" + +#: forms.py:44 +#, python-format +msgid "" +"Your file is too big (%(size)s), the maximum allowed size is " +"%(max_valid_size)s" +msgstr "上传文件太大 (%(size)s), 允许的最大文件为 %(max_valid_size)s" + +#: forms.py:54 +#, python-format +msgid "" +"You already have %(nb_avatars)d avatars, and the maximum allowed is " +"%(nb_max_avatars)d." +msgstr "您目前有 %(nb_avatars)d 个头像, 最多可以有 %(nb_max_avatars)d 个。" + +#: forms.py:71 forms.py:84 +msgid "Choices" +msgstr "选项" + +#: templates/avatar/add.html:6 templates/avatar/change.html:6 +msgid "Your current avatar: " +msgstr "您当前的头像:" + +#: templates/avatar/add.html:9 templates/avatar/change.html:9 +msgid "You haven't uploaded an avatar yet. Please upload one now." +msgstr "您还没有上传任何头像,请现在上传一个吧。" + +#: templates/avatar/add.html:13 templates/avatar/change.html:20 +msgid "Upload New Image" +msgstr "上传新照片" + +#: templates/avatar/change.html:15 +msgid "Choose new Default" +msgstr "选择默认" + +#: templates/avatar/confirm_delete.html:6 +msgid "Please select the avatars that you would like to delete." +msgstr "选择要删除的头像。" + +#: templates/avatar/confirm_delete.html:9 +#, python-format +msgid "" +"You have no avatars to delete. Please upload one now." +msgstr "" +"没有头像可以删除. 请 上传一个新头像。" + +#: templates/avatar/confirm_delete.html:15 +msgid "Delete These" +msgstr "删除" + +#: templates/notification/avatar_friend_updated/full.txt:1 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" +"%(avatar_creator)s 更新了头像 %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_friend_updated/notice.html:2 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s." +msgstr "" +"%(avatar_creator)s 更新了头像 %(avatar)s." + +#: templates/notification/avatar_updated/full.txt:1 +#, python-format +msgid "" +"Your avatar has been updated. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" +"您的头像已经更新。 %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_updated/notice.html:2 +#, python-format +msgid "You have updated your avatar %(avatar)s." +msgstr "您已经更新了头像 %(avatar)s." + +#: templatetags/avatar_tags.py:51 +msgid "Default Avatar" +msgstr "默认头像" + +#: views.py:74 +msgid "Successfully uploaded a new avatar." +msgstr "成功上传头像。" + +#: views.py:110 +msgid "Successfully updated your avatar." +msgstr "更新头像成功。" + +#: views.py:148 +msgid "Successfully deleted the requested avatars." +msgstr "成功删除头像。" From fcf1c39589513ab91dbcdd6af84a540104085875 Mon Sep 17 00:00:00 2001 From: David Lindsey Date: Thu, 3 Apr 2014 19:41:12 +0530 Subject: [PATCH 009/119] Replace remaining occurences of AUTO_GENERATE_AVATAR_SIZES with AVATAR_AUTO_GENERATE_SIZES --- avatar/conf.py | 2 +- docs/index.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/avatar/conf.py b/avatar/conf.py index e25ee91..944520b 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -25,5 +25,5 @@ class AvatarConf(AppConf): AUTO_GENERATE_SIZES = (DEFAULT_SIZE,) def configure_auto_generate_avatar_sizes(self, value): - return value or getattr(settings, 'AUTO_GENERATE_AVATAR_SIZES', + return value or getattr(settings, 'AVATAR_AUTO_GENERATE_SIZES', (self.DEFAULT_SIZE,)) diff --git a/docs/index.txt b/docs/index.txt index c1dda78..4e33b54 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -94,7 +94,7 @@ Global Settings There are a number of settings available to easily customize the avatars that appear on the site. Listed below are those settings: -AUTO_GENERATE_AVATAR_SIZES +AVATAR_AUTO_GENERATE_SIZES An iterable of integers representing the sizes of avatars to generate on upload. This can save rendering time later on if you pre-generate the resized versions. Defaults to ``(80,)`` From 17e777917690132da13a4a60736da873f99a16c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Dias=20de=20Carvalho=20Neto?= Date: Tue, 3 Jun 2014 14:47:32 -0300 Subject: [PATCH 010/119] Update django.po --- avatar/locale/pt_BR/LC_MESSAGES/django.po | 37 ++++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/avatar/locale/pt_BR/LC_MESSAGES/django.po b/avatar/locale/pt_BR/LC_MESSAGES/django.po index 690605b..e70e1dc 100644 --- a/avatar/locale/pt_BR/LC_MESSAGES/django.po +++ b/avatar/locale/pt_BR/LC_MESSAGES/django.po @@ -21,25 +21,26 @@ msgstr "" msgid "" "%(ext)s is an invalid file extension. Authorized extensions are : %" "(valid_exts_list)s" -msgstr "" +msgstr "Extensão informada inválida. Os Formatos permitidos são : %" #: forms.py:38 #, python-format msgid "" "Your file is too big (%(size)s), the maximum allowed size is %" "(max_valid_size)s" -msgstr "" +msgstr "Arquivo muito grande (%(size)s), o máximo permitido é %" +"(max_valid_size)s" #: forms.py:44 #, python-format msgid "" "You already have %(nb_avatars)d avatars, and the maximum allowed is %" "(nb_max_avatars)d." -msgstr "" +msgstr "Você já possui %(nb_avatars)d fotos. O máximo permitido é %" #: forms.py:56 forms.py:67 msgid "Choices" -msgstr "" +msgstr "Opções" #: models.py:75 #, python-format @@ -52,7 +53,7 @@ msgstr "Nova foto de perfil enviada com sucesso." #: views.py:132 msgid "Successfully updated your avatar." -msgstr "Sua foto de perfil foi atualizada com sucesso." +msgstr "Sua foto foi atualizada com sucesso." #: views.py:166 msgid "Successfully deleted the requested avatars." @@ -60,34 +61,35 @@ msgstr "As fotos de perfil selecionadas foram excluídas com sucesso." #: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " -msgstr "" +msgstr "Sua foto atual:" #: templates/avatar/add.html:8 templates/avatar/change.html:8 msgid "You haven't uploaded an avatar yet. Please upload one now." -msgstr "" +msgstr "Você ainda não possui uma foto de perfil" #: templates/avatar/add.html:12 templates/avatar/change.html:19 msgid "Upload New Image" -msgstr "" +msgstr "Enviar foto" #: templates/avatar/change.html:14 msgid "Choose new Default" -msgstr "" +msgstr "Escolher padrão" #: templates/avatar/confirm_delete.html:5 msgid "Please select the avatars that you would like to delete." -msgstr "" +msgstr "Por favor, selecione as fotos que você deseja excluir" #: templates/avatar/confirm_delete.html:8 #, python-format msgid "" "You have no avatars to delete. Please upload one now." -msgstr "" +msgstr "Você não possui uma foto. Deseja enviar uma agora?" #: templates/avatar/confirm_delete.html:14 msgid "Delete These" -msgstr "" +msgstr "Excluir estes" #: templates/notification/avatar_friend_updated/full.txt:1 #, fuzzy, python-format @@ -95,7 +97,9 @@ msgid "" "%(avatar_creator)s has updated their avatar %(avatar)s.\n" "\n" "http://%(current_site)s%(avatar_url)s\n" -msgstr "" +msgstr "%(avatar_creator)s atualizou a foto do perfil %(avatar)s.\n" +"\n" + "%(avatar_creator)s atualizou a foto de perfil " "%(avatar)s." @@ -114,7 +118,10 @@ msgid "" "Your avatar has been updated. %(avatar)s\n" "\n" "http://%(current_site)s%(avatar_url)s\n" -msgstr "" +msgstr "Sua foto de perfil foi atualizada. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + #: templates/notification/avatar_updated/notice.html:2 #, fuzzy, python-format @@ -131,7 +138,7 @@ msgstr "Foto de Perfil Padrão" #~ msgstr "Foto de Perfil Atualizada" #~ msgid "avatar have been updated" -#~ msgstr "foto de perfil foi atualizada" +#~ msgstr "sua foto de perfil foi atualizada" #~ msgid "Friend Updated Avatar" #~ msgstr "Amigo Atualizou Foto de Perfil" From eee6b08e07e60a8ec1f3c2fa2e156344e01737d2 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 10 Sep 2014 22:49:45 +0800 Subject: [PATCH 011/119] clean out --- avatar/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avatar/admin.py b/avatar/admin.py index ffaa019..8f670a9 100644 --- a/avatar/admin.py +++ b/avatar/admin.py @@ -21,7 +21,7 @@ class AvatarAdmin(admin.ModelAdmin): 'alt': six.text_type(avatar_in.user), 'size': 80, }) - return render_to_string('avatar/avatar_tag.html',context) + return render_to_string('avatar/avatar_tag.html', context) get_avatar.short_description = _('Avatar') get_avatar.allow_tags = True From 6184fb10b7a48df4e7c75485ed12b4a389dd3c3c Mon Sep 17 00:00:00 2001 From: Nikos Roussos Date: Thu, 18 Sep 2014 18:21:00 +0300 Subject: [PATCH 012/119] Use https to gravatar url --- avatar/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avatar/conf.py b/avatar/conf.py index e25ee91..de0e420 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -8,7 +8,7 @@ class AvatarConf(AppConf): DEFAULT_SIZE = 80 RESIZE_METHOD = Image.ANTIALIAS STORAGE_DIR = 'avatars' - GRAVATAR_BASE_URL = 'http://www.gravatar.com/avatar/' + GRAVATAR_BASE_URL = 'https://www.gravatar.com/avatar/' GRAVATAR_BACKUP = True GRAVATAR_DEFAULT = None DEFAULT_URL = 'avatar/img/default.jpg' From b554e65923db8e3df74f508398f86dac86411354 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 23 Apr 2015 14:55:05 -0500 Subject: [PATCH 013/119] Add new versions of python and django to travis build --- .travis.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 72162da..4e28c65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,18 +4,23 @@ python: - 2.7 - 3.2 - 3.3 + - 3.4 install: - pip install -e . - pip install -r tests/requirements.txt - pip install https://github.com/django/django/archive/${DJANGO}.zip#egg=django script: make test env: - - DJANGO=1.4.7 + - DJANGO=1.4.20 - DJANGO=1.5.3 - DJANGO=stable/1.6.x + - DJANGO=stable/1.7.x + - DJANGO=stable/1.8.x matrix: exclude: - python: 3.2 - env: DJANGO=1.4.7 + env: DJANGO=1.4.20 - python: 3.3 - env: DJANGO=1.4.7 + env: DJANGO=1.4.20 + - python: 3.4 + env: DJANGO=1.4.20 From 3d48f181f90995bd66dc436acccde9d18c5cfa3c Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 23 Apr 2015 15:10:25 -0500 Subject: [PATCH 014/119] Remove django.contrib.comments and add MIDDLEWARE_CLASSES --- tests/settings.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/settings.py b/tests/settings.py index e1c6b18..64622ac 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -14,10 +14,19 @@ INSTALLED_APPS = [ 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sites', - 'django.contrib.comments', 'avatar', ] +MIDDLEWARE_CLASSES = ( + "django.middleware.common.BrokenLinkEmailsMiddleware", + "django.middleware.common.CommonMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", +) + + ROOT_URLCONF = 'tests.urls' SITE_ID = 1 From 9355f38ac4056c3f4ba5a39bdbd13aee2d94d47b Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 23 Apr 2015 15:16:00 -0500 Subject: [PATCH 015/119] Remove BrokenLinksMiddleware --- tests/settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/settings.py b/tests/settings.py index 64622ac..c85df2d 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -18,7 +18,6 @@ INSTALLED_APPS = [ ] MIDDLEWARE_CLASSES = ( - "django.middleware.common.BrokenLinkEmailsMiddleware", "django.middleware.common.CommonMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.csrf.CsrfViewMiddleware", From 5dc77b8d07132bc6649cbf7d241ee78691aecc27 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 23 Apr 2015 15:16:59 -0500 Subject: [PATCH 016/119] Django 1.7 and 1.8 don't support Python 2.6 --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4e28c65..7373ac4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,10 @@ env: - DJANGO=stable/1.8.x matrix: exclude: + - python: 2.6 + env: DJANGO=stable/1.7.x + - python: 2.6 + env: DJANGO=stable/1.8.x - python: 3.2 env: DJANGO=1.4.20 - python: 3.3 From 51b336accce1a05ae7a7cf52ec19738a9f8b88d4 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 23 Apr 2015 15:33:26 -0500 Subject: [PATCH 017/119] Specify django versions --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7373ac4..796701a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,16 +12,16 @@ install: script: make test env: - DJANGO=1.4.20 - - DJANGO=1.5.3 - - DJANGO=stable/1.6.x - - DJANGO=stable/1.7.x - - DJANGO=stable/1.8.x + - DJANGO=1.5.12 + - DJANGO=1.6.11 + - DJANGO=1.7.7 + - DJANGO=1.8 matrix: exclude: - python: 2.6 - env: DJANGO=stable/1.7.x + env: DJANGO=1.7.7 - python: 2.6 - env: DJANGO=stable/1.8.x + env: DJANGO=1.8 - python: 3.2 env: DJANGO=1.4.20 - python: 3.3 From 54dde3a6a55be97e2d1814b483564625ad676fce Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 23 Apr 2015 15:45:32 -0500 Subject: [PATCH 018/119] One more attempt to get the build to work on Django 1.8 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 796701a..5df26e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ python: install: - pip install -e . - pip install -r tests/requirements.txt - - pip install https://github.com/django/django/archive/${DJANGO}.zip#egg=django + - pip install Django==${DJANGO} script: make test env: - DJANGO=1.4.20 From 7059011aab8415fa324f97d1950347cbd4207eef Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Fri, 24 Apr 2015 16:51:28 -0300 Subject: [PATCH 019/119] Update index.txt replace AUTO_GENERATE_AVATAR_SIZES with AVATAR_ prefixed setting. --- docs/index.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.txt b/docs/index.txt index 2d2dc6a..7c63af6 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -126,7 +126,7 @@ Management Commands This application does include one management command: ``rebuild_avatars``. It takes no arguments and, when run, re-renders all of the thumbnails for all of -the avatars for the pixel sizes specified in the ``AUTO_GENERATE_AVATAR_SIZES`` +the avatars for the pixel sizes specified in the ``AVATAR_AUTO_GENERATE_SIZES`` setting. From 449abb90370aeae609e4c284f3453981f1689025 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sun, 26 Apr 2015 23:15:41 -0500 Subject: [PATCH 020/119] Added CHANGELOG.rst --- CHANGELOG.rst | 8 ++++++++ tests/tests.py | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..5b17f5e --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,8 @@ +Changelog +========= + +* 2.1 (not released) + * Changed Gravatar link to use HTTPS by default + * Fixed a bug where the admin list page should show the incorrect avatar + * Updated render_primary view to accept usernames with @ signs in them + * Updated translations (added Dutch, Japanese, and Simple Chinese) diff --git a/tests/tests.py b/tests/tests.py index ee31c95..73d89af 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,8 +1,10 @@ import os.path +from django.contrib.admin.sites import AdminSite from django.test import TestCase from django.core.urlresolvers import reverse +from avatar.admin import AvatarAdmin from avatar.conf import settings from avatar.util import get_primary_avatar, get_user_model from avatar.models import Avatar @@ -18,15 +20,28 @@ def upload_helper(o, filename): return response -class AvatarUploadTests(TestCase): +class AvatarTests(TestCase): def setUp(self): self.testdatapath = os.path.join(os.path.dirname(__file__), "data") self.user = get_user_model().objects.create_user('test', 'lennon@thebeatles.com', 'testpassword') self.user.save() self.client.login(username='test', password='testpassword') + self.site = AdminSite() Image.init() + def testAdminGetAvatarReturnsDifferentImageTags(self): + self.testNormalImageUpload() + self.testNormalImageUpload() + primary = Avatar.objects.get(primary=True) + old = Avatar.objects.get(primary=False) + + aa = AvatarAdmin(Avatar, self.site) + primary_link = aa.get_avatar(primary) + old_link = aa.get_avatar(old) + + self.assertNotEqual(primary_link, old_link) + def testNonImageUpload(self): response = upload_helper(self, "nonimagefile") self.assertEqual(response.status_code, 200) From e01effee065058d551c2b3b289d3380c2020bc8d Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sun, 26 Apr 2015 23:24:29 -0500 Subject: [PATCH 021/119] Update Changelog, __version__, and PyPI classifiers --- CHANGELOG.rst | 2 +- avatar/__init__.py | 2 +- setup.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5b17f5e..a13ac67 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,6 @@ Changelog * 2.1 (not released) * Changed Gravatar link to use HTTPS by default - * Fixed a bug where the admin list page should show the incorrect avatar + * Fixed a bug where the admin avatar list page would only show a user's primary avatar * Updated render_primary view to accept usernames with @ signs in them * Updated translations (added Dutch, Japanese, and Simple Chinese) diff --git a/avatar/__init__.py b/avatar/__init__.py index 3b3dacb..d980f27 100644 --- a/avatar/__init__.py +++ b/avatar/__init__.py @@ -1 +1 @@ -__version__ = '2.0' +__version__ = '2.1' diff --git a/setup.py b/setup.py index cbf2829..88b4500 100644 --- a/setup.py +++ b/setup.py @@ -35,6 +35,7 @@ setup( 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', ], keywords='avatar, django', author='Eric Florenzano', From 26087d871d4912e188121614fa900a979a902623 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 2 May 2015 13:13:51 -0500 Subject: [PATCH 022/119] Add south and django migrations --- CHANGELOG.rst | 2 + avatar/migrations/0001_initial.py | 28 ++++++++++ avatar/migrations/__init__.py | 21 ++++++++ avatar/south_migrations/0001_initial.py | 71 +++++++++++++++++++++++++ avatar/south_migrations/__init__.py | 0 5 files changed, 122 insertions(+) create mode 100644 avatar/migrations/0001_initial.py create mode 100644 avatar/migrations/__init__.py create mode 100644 avatar/south_migrations/0001_initial.py create mode 100644 avatar/south_migrations/__init__.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a13ac67..4378da2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,8 @@ Changelog ========= * 2.1 (not released) + * Django 1.7 and 1.8 support + * Add South and Django migrations * Changed Gravatar link to use HTTPS by default * Fixed a bug where the admin avatar list page would only show a user's primary avatar * Updated render_primary view to accept usernames with @ signs in them diff --git a/avatar/migrations/0001_initial.py b/avatar/migrations/0001_initial.py new file mode 100644 index 0000000..75ef204 --- /dev/null +++ b/avatar/migrations/0001_initial.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.utils.timezone +import avatar.models +import django.core.files.storage +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Avatar', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('primary', models.BooleanField(default=False)), + ('avatar', models.ImageField(storage=django.core.files.storage.FileSystemStorage(), max_length=1024, upload_to=avatar.models.avatar_file_path, blank=True)), + ('date_uploaded', models.DateTimeField(default=django.utils.timezone.now)), + ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/avatar/migrations/__init__.py b/avatar/migrations/__init__.py new file mode 100644 index 0000000..3b10179 --- /dev/null +++ b/avatar/migrations/__init__.py @@ -0,0 +1,21 @@ +""" +Django migrations for django-avatar app + +This package does not contain South migrations. South migrations can be found +in the ``south_migrations`` package. +""" + +SOUTH_ERROR_MESSAGE = """\n +For South support, customize the SOUTH_MIGRATION_MODULES setting like so: + + SOUTH_MIGRATION_MODULES = { + 'django-avatar': 'avatar.south_migrations', + } +""" + +# Ensure the user is not using Django 1.6 or below with South +try: + from django.db import migrations # noqa +except ImportError: + from django.core.exceptions import ImproperlyConfigured + raise ImproperlyConfigured(SOUTH_ERROR_MESSAGE) diff --git a/avatar/south_migrations/0001_initial.py b/avatar/south_migrations/0001_initial.py new file mode 100644 index 0000000..336c595 --- /dev/null +++ b/avatar/south_migrations/0001_initial.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'Avatar' + db.create_table(u'avatar_avatar', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('primary', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('avatar', self.gf('django.db.models.fields.files.ImageField')(max_length=1024, blank=True)), + ('date_uploaded', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + )) + db.send_create_signal(u'avatar', ['Avatar']) + + def backwards(self, orm): + # Deleting model 'Avatar' + db.delete_table(u'avatar_avatar') + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'avatar.avatar': { + 'Meta': {'object_name': 'Avatar'}, + 'avatar': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}), + 'date_uploaded': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['avatar'] diff --git a/avatar/south_migrations/__init__.py b/avatar/south_migrations/__init__.py new file mode 100644 index 0000000..e69de29 From 1c69ecc73c855b421ddd90672827ce941ed0fc71 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 2 May 2015 13:23:27 -0500 Subject: [PATCH 023/119] Fix unicode literals for Python 3.2 --- avatar/south_migrations/0001_initial.py | 41 +++++++++++++------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/avatar/south_migrations/0001_initial.py b/avatar/south_migrations/0001_initial.py index 336c595..a0f58f0 100644 --- a/avatar/south_migrations/0001_initial.py +++ b/avatar/south_migrations/0001_initial.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from __future__ import unicode_literals from south.utils import datetime_utils as datetime from south.db import db from south.v2 import SchemaMigration @@ -8,61 +9,61 @@ class Migration(SchemaMigration): def forwards(self, orm): # Adding model 'Avatar' - db.create_table(u'avatar_avatar', ( - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + db.create_table('avatar_avatar', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), ('primary', self.gf('django.db.models.fields.BooleanField')(default=False)), ('avatar', self.gf('django.db.models.fields.files.ImageField')(max_length=1024, blank=True)), ('date_uploaded', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), )) - db.send_create_signal(u'avatar', ['Avatar']) + db.send_create_signal('avatar', ['Avatar']) def backwards(self, orm): # Deleting model 'Avatar' - db.delete_table(u'avatar_avatar') + db.delete_table('avatar_avatar') models = { - u'auth.group': { + 'auth.group': { 'Meta': {'object_name': 'Group'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) }, - u'auth.permission': { - 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - u'auth.user': { + 'auth.user': { 'Meta': {'object_name': 'User'}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Permission']"}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, - u'avatar.avatar': { + 'avatar.avatar': { 'Meta': {'object_name': 'Avatar'}, 'avatar': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}), 'date_uploaded': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) }, - u'contenttypes.contenttype': { + 'contenttypes.contenttype': { 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) } From 1197dbe739486f8c5e7974c2ddfb6bffbdccfd50 Mon Sep 17 00:00:00 2001 From: Victor Kotseruba Date: Fri, 12 Jun 2015 01:22:02 +0300 Subject: [PATCH 024/119] `EXPOSE_USERNAMES` prevents sensitive information leakage --- avatar/conf.py | 1 + avatar/models.py | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/avatar/conf.py b/avatar/conf.py index 4d7f01f..14a263a 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -18,6 +18,7 @@ class AvatarConf(AppConf): THUMB_QUALITY = 85 HASH_FILENAMES = False HASH_USERDIRNAMES = False + EXPOSE_USERNAMES = True ALLOWED_FILE_EXTS = None CACHE_TIMEOUT = 60 * 60 STORAGE = settings.DEFAULT_FILE_STORAGE diff --git a/avatar/models.py b/avatar/models.py index 5bc3a52..bca0918 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -8,6 +8,7 @@ from django.core.files import File from django.core.files.base import ContentFile from django.core.files.storage import get_storage_class from django.utils.translation import ugettext as _ +from django.utils.encoding import force_text from django.utils import six from django.db.models import signals @@ -26,10 +27,12 @@ avatar_storage = get_storage_class(settings.AVATAR_STORAGE)() def avatar_file_path(instance=None, filename=None, size=None, ext=None): tmppath = [settings.AVATAR_STORAGE_DIR] if settings.AVATAR_HASH_USERDIRNAMES: - tmp = hashlib.md5(get_username(instance.user)).hexdigest() - tmppath.extend([tmp[0], tmp[1], get_username(instance.user)]) - else: + tmp = hashlib.md5(force_bytes(get_username(instance.user))).hexdigest() + tmppath.extend(tmp[0:2]) + if settings.AVATAR_EXPOSE_USERNAMES: tmppath.append(get_username(instance.user)) + else: + tmppath.append(force_text(instance.user.pk)) if not filename: # Filename already stored in database filename = instance.avatar.name From f4c5e9165fcdcc118b848f076dd9363bcebefd58 Mon Sep 17 00:00:00 2001 From: Dave Gaeddert Date: Thu, 16 Jul 2015 15:28:52 -0500 Subject: [PATCH 025/119] Add GRAVATAR_DEFAULT and AVATAR_MAX_SIZE to docs --- docs/index.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/index.txt b/docs/index.txt index 7c63af6..780993d 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -117,10 +117,19 @@ AVATAR_GRAVATAR_BACKUP ``Avatar`` instance is found in the system for the given user. Defaults to True. +GRAVATAR_DEFAULT + A string determining the style of the default Gravatar. Available options + listed in the + (Gravatar documentation)[https://en.gravatar.com/site/implement/images/#default-image]. + Ex. 'retro'. Defaults to None. + AVATAR_DEFAULT_URL The default URL to default to if ``AVATAR_GRAVATAR_BACKUP`` is set to False and there is no ``Avatar`` instance found in the system for the given user. +AVATAR_MAX_SIZE + File size limit for avatar upload. Default is ``1024 * 1024`` (1mb). + Management Commands ------------------- From 200e4ae047e883451af6a1fc55bbc931fcfaddfa Mon Sep 17 00:00:00 2001 From: Dave Gaeddert Date: Sat, 18 Jul 2015 23:30:37 -0500 Subject: [PATCH 026/119] Rename GRAVATAR_DEFAULT to AVATAR_GRAVATAR_DEFAULT in docs --- docs/index.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.txt b/docs/index.txt index 780993d..c16a9c4 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -117,7 +117,7 @@ AVATAR_GRAVATAR_BACKUP ``Avatar`` instance is found in the system for the given user. Defaults to True. -GRAVATAR_DEFAULT +AVATAR_GRAVATAR_DEFAULT A string determining the style of the default Gravatar. Available options listed in the (Gravatar documentation)[https://en.gravatar.com/site/implement/images/#default-image]. From f69b5c64d6b931c53387cdbb6038d19b8803f4dd Mon Sep 17 00:00:00 2001 From: Adam Dobrawy Date: Sun, 19 Jul 2015 15:29:42 +0200 Subject: [PATCH 027/119] Add polish locale --- avatar/locale/pl/LC_MESSAGES/django.mo | Bin 0 -> 3152 bytes avatar/locale/pl/LC_MESSAGES/django.po | 146 +++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 avatar/locale/pl/LC_MESSAGES/django.mo create mode 100644 avatar/locale/pl/LC_MESSAGES/django.po diff --git a/avatar/locale/pl/LC_MESSAGES/django.mo b/avatar/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..ee61fdf17520f007f4f4224370b6d1d423b6297f GIT binary patch literal 3152 zcmb_eOK%%h6dq`K)I3`r-2gfilE!LgVux0wZX5_r3z2A(mW0x>FxQ?N`zGUi&D@zx zXXvWpv13Oi)E~fxU3VzE)H`-;QH5Z|4)!eg?mTR#Nu*LS()gRXa~|J0=bm$Y@5sUL zEL<<+eg*f>xL?J6;}QJe`U}_q{ta9OUV7BB6z~V&J z9{^{7tH2Y$Z-K7^e*(S%{1x~-&^l;YR{)2BSAha}4!8}h0S`R}-@panOTb&eCE$-h z!{Z;|J#ajL7m4@ZLFyXt(vy}I89AVld-G7n>jcomJOecTmw?XzKLZ{IO5hmq7H}N6 z1tj1fKojS|Qs(C<(D3~l_$lx=;2d!FsVtr^fQIicK$FKmfriH-k^{PFj*Pv-xDkT& z0&a5|ofp$5#FV4qhjgTu;SN`+EtBu((pAesSuD61T%eoQ$Ha&fAgBqp$pYp#T0Uoi z^2?e!OjFo%S-@QiI$ZdaiBKV1)=sI^34&g2YHDnv75YAxK|_mxmvtf22z{@tOR&$c z2QVr$F-byhGEca)COl5~z@-*SIy4^!9p#Gz9tW#X@Hy4sHPvb0gKl_2!RZM zVLoOxF$KvwD^svCTGq0!*0E3RMc4kA`=&o@7xGs2Y`)msaevW|lzFUceBk(R8JH%C5X^S5H&*RBd|ZL}j{CfuMbvZwljJU%4ve zK4dzuS9~V5X9iS_=3UmM1=aLf6w|C^t%Q40Y`nY9BB^xC2{z`SB-7hmZnHqp6<9ggisolD_6aeRbu$Ju{RujMuntpOY=+ z3fZpFOj87kQnQFZBsouUF|Es$llXv1(Emqu zqKwP*Nsf244o=;rpsqapV;qn$^9%}%Zj@qpsI7qIcWxRR>hHlpRkP} z#9U5P#QHaBigqrrV$&C@4>SMQF|J4o-b2-d+rO!zxJ$lDbi)0F<3ra$O_NA@Xy(xm z3|ssEI0Saav`3H+JR0V+!(ge`TIUqSP34EymAEMoh#3Hw)T$fzZ+kMf7K*1lh1RML z`(GL*><&KA$|^ER8^QJ+KgNc_)K4hXp}hOm-ESOgIX5GCx+v~`k3%BT8!TZm&P_uq z^9rHSSTSE$qU}5DL$RT;DAxU(3=%2rjD-VMATQRlMbl=9HJ@$}REfF_%=SD3w(mrf z)KhLN!T*Ogj*Bka&~cY}k|86#P$&3eUOdrCnhZ%mw~9Rvhl_=yj1nxvLJ@jPFpORw zx?QyY@Q*+y+t_(PxXNW&B-ufJZO2yU{oA`Y0@n0M!uD{n&yg`?J;+vni@7pxb@JpR zkRkObPji4iO&qdDt3-*?f$7B^m5d+i@W}0EoQmC&d+XsJ2c@l, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: django-avatar 0.0.2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-19 15:28+0200\n" +"PO-Revision-Date: 2015-07-19 15:28+0100\n" +"Last-Translator: Adam Dobrawy \n" +"Language-Team: Adam Dobrawy \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 1.5.4\n" + +#: admin.py:26 +msgid "Avatar" +msgstr "Avatar" + +#: forms.py:24 +msgid "avatar" +msgstr "avatar" + +#: forms.py:37 +#, python-format +msgid "" +"%(ext)s is an invalid file extension. Authorized extensions are : " +"%(valid_exts_list)s" +msgstr "" +"%(ext)s jest nieprawidłowym rozszerzeniem. Dozwolone rozszerzenia to: " +"%(valid_exts_list)s" + +#: forms.py:44 +#, python-format +msgid "" +"Your file is too big (%(size)s), the maximum allowed size is " +"%(max_valid_size)s" +msgstr "" +"Twój plik jest zbyt duży (%(size)s), maksymalny dopuszcalny rozmiar wynosi " +"%(max_valid_size)s" + +#: forms.py:54 +#, python-format +msgid "" +"You already have %(nb_avatars)d avatars, and the maximum allowed is " +"%(nb_max_avatars)d." +msgstr "" +"Aktualnie masz %(nb_avatars)d avatarów, podczas gdy maksymalna dopuszczalna " +"liczba wynosi %(nb_max_avatars)d." + +#: forms.py:71 forms.py:84 +msgid "Choices" +msgstr "Opcje wyboru" + +#: templates/avatar/add.html:6 templates/avatar/change.html:6 +msgid "Your current avatar: " +msgstr "Twój aktualny avatar" + +#: templates/avatar/add.html:9 templates/avatar/change.html:9 +msgid "You haven't uploaded an avatar yet. Please upload one now." +msgstr "Nie masz aktualnie żadnych avatarów. Prosimy wyślij teraz. " + +#: templates/avatar/add.html:13 templates/avatar/change.html:20 +msgid "Upload New Image" +msgstr "Wyślij nowy obraz" + +#: templates/avatar/change.html:15 +msgid "Choose new Default" +msgstr "Wybierz nowy domyślny" + +#: templates/avatar/confirm_delete.html:6 +msgid "Please select the avatars that you would like to delete." +msgstr "Wybierz avatar, który chcesz usunąć." + +#: templates/avatar/confirm_delete.html:9 +#, python-format +msgid "" +"You have no avatars to delete. Please upload one now." +msgstr "" +"Nie masz avatarów do usunięcia. Prosimy dodaj nowy." + +#: templates/avatar/confirm_delete.html:15 +msgid "Delete These" +msgstr "Usuń wybrane" + +#: templates/notification/avatar_friend_updated/full.txt:1 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" +"%(avatar_creator)s zaktualizował / zaktualizowała avatar %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_friend_updated/notice.html:2 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s." +msgstr "" +"%(avatar_creator)s zaktualizował / " +"zaktualizowała %(avatar)s." + +#: templates/notification/avatar_updated/full.txt:1 +#, python-format +msgid "" +"Your avatar has been updated. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" +"Twój avatar został zaktualizowany %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_updated/notice.html:2 +#, python-format +msgid "You have updated your avatar %(avatar)s." +msgstr "" +"Zaktualizowałeś / zaktualizowałaś swój avatar " +"%(avatar)s." + +#: templatetags/avatar_tags.py:51 +msgid "Default Avatar" +msgstr "Domyślny avatar" + +#: views.py:74 +msgid "Successfully uploaded a new avatar." +msgstr "Pomyślnie wysłano nowy avatar." + +#: views.py:110 +msgid "Successfully updated your avatar." +msgstr "Pmyślnie zaktualizowano Twój avatar." + +#: views.py:148 +msgid "Successfully deleted the requested avatars." +msgstr "Pomyślnie usunięto wskazany avatar." From 73ad17491ec8fd56e57427fb8aea1a032e02b29b Mon Sep 17 00:00:00 2001 From: Adam Dobrawy Date: Sun, 19 Jul 2015 15:46:27 +0200 Subject: [PATCH 028/119] Fix typo in polish locale --- avatar/locale/pl/LC_MESSAGES/django.mo | Bin 3152 -> 3153 bytes avatar/locale/pl/LC_MESSAGES/django.po | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/avatar/locale/pl/LC_MESSAGES/django.mo b/avatar/locale/pl/LC_MESSAGES/django.mo index ee61fdf17520f007f4f4224370b6d1d423b6297f..c6032a3dff5ff1ebe63dadadd4c83aa92a477400 100644 GIT binary patch delta 120 zcmca0aZzG}3S+1`0|UbzP6h@AApHbL3jt|XE(V4?AT0r;BY|`~kd6k@4}r8DkhbM! zU\n" "Language-Team: Adam Dobrawy \n" "Language: pl\n" @@ -139,7 +139,7 @@ msgstr "Pomyślnie wysłano nowy avatar." #: views.py:110 msgid "Successfully updated your avatar." -msgstr "Pmyślnie zaktualizowano Twój avatar." +msgstr "Pomyślnie zaktualizowano Twój avatar." #: views.py:148 msgid "Successfully deleted the requested avatars." From 97b1ffd0204f484b8d62731b64f3175e7007c272 Mon Sep 17 00:00:00 2001 From: Kaloian Minkov Date: Thu, 23 Jul 2015 11:23:33 +0300 Subject: [PATCH 029/119] Add Django 1.8+ style Meta app_label to Avatar model to prevent RemovedInDjango19Warning --- avatar/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/avatar/models.py b/avatar/models.py index 5bc3a52..1463df0 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -70,6 +70,9 @@ class Avatar(models.Model): blank=True) date_uploaded = models.DateTimeField(default=now) + class Meta: + app_label = 'avatar' + def __unicode__(self): return _(six.u('Avatar for %s')) % self.user From be8a172e56be1ffcfd47cb48c80e42de39124a7a Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 23 Jul 2015 08:43:15 -0500 Subject: [PATCH 030/119] Remove load url from future --- avatar/templates/avatar/add.html | 1 - avatar/templates/avatar/change.html | 1 - avatar/templates/avatar/confirm_delete.html | 1 - avatar/templates/notification/avatar_friend_updated/notice.html | 2 +- 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/avatar/templates/avatar/add.html b/avatar/templates/avatar/add.html index 7a04b34..9b4fed6 100644 --- a/avatar/templates/avatar/add.html +++ b/avatar/templates/avatar/add.html @@ -1,6 +1,5 @@ {% extends "avatar/base.html" %} {% load i18n avatar_tags %} -{% load url from future %} {% block content %}

{% trans "Your current avatar: " %}

diff --git a/avatar/templates/avatar/change.html b/avatar/templates/avatar/change.html index 7e7b3d2..8d27359 100644 --- a/avatar/templates/avatar/change.html +++ b/avatar/templates/avatar/change.html @@ -1,6 +1,5 @@ {% extends "avatar/base.html" %} {% load i18n avatar_tags %} -{% load url from future %} {% block content %}

{% trans "Your current avatar: " %}

diff --git a/avatar/templates/avatar/confirm_delete.html b/avatar/templates/avatar/confirm_delete.html index 373131d..f81c815 100644 --- a/avatar/templates/avatar/confirm_delete.html +++ b/avatar/templates/avatar/confirm_delete.html @@ -1,6 +1,5 @@ {% extends "avatar/base.html" %} {% load i18n %} -{% load url from future %} {% block content %}

{% trans "Please select the avatars that you would like to delete." %}

diff --git a/avatar/templates/notification/avatar_friend_updated/notice.html b/avatar/templates/notification/avatar_friend_updated/notice.html index c2ba8bc..79c5d54 100644 --- a/avatar/templates/notification/avatar_friend_updated/notice.html +++ b/avatar/templates/notification/avatar_friend_updated/notice.html @@ -1,2 +1,2 @@ -{% load i18n %}{% load url from future %}{% url 'profile_detail' username=user.username as user_url %}{# TODO: support custom user models via get_username; actually, is this template even used anymore? #} +{% load i18n %}{% url 'profile_detail' username=user.username as user_url %}{# TODO: support custom user models via get_username; actually, is this template even used anymore? #} {% blocktrans with user as avatar_creator and avatar.get_absolute_url as avatar_url %}{{ avatar_creator }} has updated their avatar {{ avatar }}.{% endblocktrans %} From b4c212dee87e7174ab1775570f87c0e1fb22496b Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 23 Jul 2015 08:46:04 -0500 Subject: [PATCH 031/119] Updated changelog --- CHANGELOG.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4378da2..16b6db8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,11 @@ Changelog ========= -* 2.1 (not released) +* 2.1.1 (not released) + * Added Polish locale + * Fixed RemovedInDjango19Warning warnings + +* 2.1 (May 2, 2015) * Django 1.7 and 1.8 support * Add South and Django migrations * Changed Gravatar link to use HTTPS by default From 6d2ad4a8bdd6081d7a682dbd14b5d6c0fd5daab2 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 23 Jul 2015 10:03:04 -0500 Subject: [PATCH 032/119] Add back load url from future, will remove when 1.9 is out --- avatar/templates/avatar/add.html | 1 + avatar/templates/avatar/change.html | 1 + avatar/templates/avatar/confirm_delete.html | 1 + avatar/templates/notification/avatar_friend_updated/full.txt | 2 +- avatar/templates/notification/avatar_friend_updated/notice.html | 2 +- 5 files changed, 5 insertions(+), 2 deletions(-) diff --git a/avatar/templates/avatar/add.html b/avatar/templates/avatar/add.html index 9b4fed6..7a04b34 100644 --- a/avatar/templates/avatar/add.html +++ b/avatar/templates/avatar/add.html @@ -1,5 +1,6 @@ {% extends "avatar/base.html" %} {% load i18n avatar_tags %} +{% load url from future %} {% block content %}

{% trans "Your current avatar: " %}

diff --git a/avatar/templates/avatar/change.html b/avatar/templates/avatar/change.html index 8d27359..7e7b3d2 100644 --- a/avatar/templates/avatar/change.html +++ b/avatar/templates/avatar/change.html @@ -1,5 +1,6 @@ {% extends "avatar/base.html" %} {% load i18n avatar_tags %} +{% load url from future %} {% block content %}

{% trans "Your current avatar: " %}

diff --git a/avatar/templates/avatar/confirm_delete.html b/avatar/templates/avatar/confirm_delete.html index f81c815..373131d 100644 --- a/avatar/templates/avatar/confirm_delete.html +++ b/avatar/templates/avatar/confirm_delete.html @@ -1,5 +1,6 @@ {% extends "avatar/base.html" %} {% load i18n %} +{% load url from future %} {% block content %}

{% trans "Please select the avatars that you would like to delete." %}

diff --git a/avatar/templates/notification/avatar_friend_updated/full.txt b/avatar/templates/notification/avatar_friend_updated/full.txt index 9510956..d5197a6 100644 --- a/avatar/templates/notification/avatar_friend_updated/full.txt +++ b/avatar/templates/notification/avatar_friend_updated/full.txt @@ -1,4 +1,4 @@ -{% load i18n %}{% blocktrans with user as avatar_creator and avatar.get_absolute_url as avatar_url %}{{ avatar_creator }} has updated their avatar {{ avatar }}. +{% load i18n %}{% load url from future %}{% blocktrans with user as avatar_creator and avatar.get_absolute_url as avatar_url %}{{ avatar_creator }} has updated their avatar {{ avatar }}. http://{{ current_site }}{{ avatar_url }} {% endblocktrans %} diff --git a/avatar/templates/notification/avatar_friend_updated/notice.html b/avatar/templates/notification/avatar_friend_updated/notice.html index 79c5d54..c2ba8bc 100644 --- a/avatar/templates/notification/avatar_friend_updated/notice.html +++ b/avatar/templates/notification/avatar_friend_updated/notice.html @@ -1,2 +1,2 @@ -{% load i18n %}{% url 'profile_detail' username=user.username as user_url %}{# TODO: support custom user models via get_username; actually, is this template even used anymore? #} +{% load i18n %}{% load url from future %}{% url 'profile_detail' username=user.username as user_url %}{# TODO: support custom user models via get_username; actually, is this template even used anymore? #} {% blocktrans with user as avatar_creator and avatar.get_absolute_url as avatar_url %}{{ avatar_creator }} has updated their avatar {{ avatar }}.{% endblocktrans %} From d823165dcf88475ff6cb1d6c24ae3f4151343397 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 10 Aug 2015 09:37:28 -0500 Subject: [PATCH 033/119] Update maintainer --- CONTRIBUTORS.txt | 4 ++-- setup.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index a487c5f..af1dd9e 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -1,4 +1,4 @@ This application was originally written by Eric Florenzano. -It is now maintained by Jannis Leidel and a league of awesome contributors. +It is now maintained by Grant McConnaughey and a league of awesome contributors. -See the full list here: https://github.com/jezdez/django-avatar/graphs/contributors +See the full list here: https://github.com/grantmcconnaughey/django-avatar/graphs/contributors diff --git a/setup.py b/setup.py index 88b4500..718b35a 100644 --- a/setup.py +++ b/setup.py @@ -40,9 +40,9 @@ setup( keywords='avatar, django', author='Eric Florenzano', author_email='floguy@gmail.com', - maintainer='Jannis Leidel', - maintainer_email='jannis@leidel.info', - url='http://github.com/jezdez/django-avatar/', + maintainer='Grant McConnaughey', + maintainer_email='grantmcconnaughey@gmail.com', + url='http://github.com/grantmcconnaughey/django-avatar/', license='BSD', packages=find_packages(exclude=['tests']), package_data={ From 8fec26843807e4842be79b74ab3e33273005d50f Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 10 Aug 2015 09:38:58 -0500 Subject: [PATCH 034/119] Update changelog --- CHANGELOG.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 16b6db8..4e46d6b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,14 +1,10 @@ Changelog ========= -* 2.1.1 (not released) - * Added Polish locale - * Fixed RemovedInDjango19Warning warnings - -* 2.1 (May 2, 2015) +* 2.1 (August 10, 2015) * Django 1.7 and 1.8 support * Add South and Django migrations * Changed Gravatar link to use HTTPS by default * Fixed a bug where the admin avatar list page would only show a user's primary avatar * Updated render_primary view to accept usernames with @ signs in them - * Updated translations (added Dutch, Japanese, and Simple Chinese) + * Updated translations (added Dutch, Japanese, Polish, and Simple Chinese) From 50acf18d6a0358a8423328f3e4d57937b7407489 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 10 Aug 2015 09:40:54 -0500 Subject: [PATCH 035/119] Update travis URL --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 151d298..4606cd8 100644 --- a/README.rst +++ b/README.rst @@ -2,8 +2,8 @@ django-avatar ============= -.. image:: https://secure.travis-ci.org/jezdez/django-avatar.png - :target: http://travis-ci.org/jezdez/django-avatar +.. image:: https://travis-ci.org/grantmcconnaughey/django-avatar.svg + :target: https://travis-ci.org/grantmcconnaughey/django-avatar Django-avatar is a reusable application for handling user avatars. It has the ability to default to Gravatar if no avatar is found for a certain user. From 7fdcd98410d4c86ebe84919f3dd50083b4b0b62f Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 10 Aug 2015 09:42:32 -0500 Subject: [PATCH 036/119] Set version 2.1.1 --- CHANGELOG.rst | 8 ++++++-- avatar/__init__.py | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4e46d6b..419adeb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,10 +1,14 @@ Changelog ========= -* 2.1 (August 10, 2015) +* 2.1.1 (August 10, 2015) + * Added Polish locale + * Fixed RemovedInDjango19Warning warnings + +* 2.1 (May 2, 2015) * Django 1.7 and 1.8 support * Add South and Django migrations * Changed Gravatar link to use HTTPS by default * Fixed a bug where the admin avatar list page would only show a user's primary avatar * Updated render_primary view to accept usernames with @ signs in them - * Updated translations (added Dutch, Japanese, Polish, and Simple Chinese) + * Updated translations (added Dutch, Japanese, and Simple Chinese) diff --git a/avatar/__init__.py b/avatar/__init__.py index d980f27..55fa725 100644 --- a/avatar/__init__.py +++ b/avatar/__init__.py @@ -1 +1 @@ -__version__ = '2.1' +__version__ = '2.1.1' From bb520fe504cbc93bb44788b707888feeb9d10d6f Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 10 Aug 2015 09:49:26 -0500 Subject: [PATCH 037/119] Update Makefile --- Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile b/Makefile index 09f95cb..62cf599 100644 --- a/Makefile +++ b/Makefile @@ -7,3 +7,12 @@ test: flake8 avatar --ignore=E124,E501,E127,E128 coverage run --branch --source=avatar `which django-admin.py` test tests coverage report + +publish: clean + python setup.py sdist + twine upload dist/* + +clean: + rm -vrf ./build ./dist ./*.egg-info + find . -name '*.pyc' -delete + find . -name '*.tgz' -delete From c66e2c2fa8b74b778869ef123bc776c4b02538bb Mon Sep 17 00:00:00 2001 From: teolemon Date: Tue, 11 Aug 2015 21:15:10 +0200 Subject: [PATCH 038/119] translate string in French --- avatar/locale/fr/LC_MESSAGES/django.po | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/avatar/locale/fr/LC_MESSAGES/django.po b/avatar/locale/fr/LC_MESSAGES/django.po index 726089b..5312106 100644 --- a/avatar/locale/fr/LC_MESSAGES/django.po +++ b/avatar/locale/fr/LC_MESSAGES/django.po @@ -44,7 +44,7 @@ msgstr "" #: forms.py:56 forms.py:67 msgid "Choices" -msgstr "" +msgstr "Choix" #: models.py:75 #, python-format @@ -122,6 +122,9 @@ msgid "" "\n" "http://%(current_site)s%(avatar_url)s\n" msgstr "" +"Votre avatar a été mis à jour. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" #: templates/notification/avatar_updated/notice.html:2 #, python-format From 1c56ed5dbcef8f3bd7e6198d4195c5286bebedc7 Mon Sep 17 00:00:00 2001 From: Danny Browne Date: Fri, 4 Sep 2015 12:58:32 -0400 Subject: [PATCH 039/119] added database-level enforcement of unique user+primary pair in Avatar model --- avatar/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/avatar/models.py b/avatar/models.py index 1463df0..e7127ff 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -72,6 +72,7 @@ class Avatar(models.Model): class Meta: app_label = 'avatar' + unique_together = ('user', 'primary') def __unicode__(self): return _(six.u('Avatar for %s')) % self.user From 00cc973d477a96c73665815c6a19755301c0e0b2 Mon Sep 17 00:00:00 2001 From: Danny Browne Date: Fri, 4 Sep 2015 13:14:14 -0400 Subject: [PATCH 040/119] added django migration --- .../0002_add_user_primary_unique_together.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 avatar/migrations/0002_add_user_primary_unique_together.py diff --git a/avatar/migrations/0002_add_user_primary_unique_together.py b/avatar/migrations/0002_add_user_primary_unique_together.py new file mode 100755 index 0000000..c9bfb35 --- /dev/null +++ b/avatar/migrations/0002_add_user_primary_unique_together.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('avatar', '0001_initial'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='avatar', + unique_together=set([('user', 'primary')]), + ), + ] From 98bf19afae17c2c85fd60a3edf71ef466555d880 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 24 Sep 2015 10:26:48 -0500 Subject: [PATCH 041/119] Update Django/Python versions in Travis --- .travis.yml | 20 ++++++-------------- CHANGELOG.rst | 6 ++++++ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5df26e5..a6242c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,22 @@ language: python python: - - 2.6 - 2.7 - 3.2 - 3.3 - 3.4 + - 3.5 install: - pip install -e . - pip install -r tests/requirements.txt - pip install Django==${DJANGO} script: make test env: - - DJANGO=1.4.20 - - DJANGO=1.5.12 - - DJANGO=1.6.11 - - DJANGO=1.7.7 - - DJANGO=1.8 + - DJANGO=1.7.10 + - DJANGO=1.8.4 + - DJANGO=1.9a1 matrix: exclude: - - python: 2.6 - env: DJANGO=1.7.7 - - python: 2.6 - env: DJANGO=1.8 - python: 3.2 - env: DJANGO=1.4.20 + env: DJANGO=1.9a1 - python: 3.3 - env: DJANGO=1.4.20 - - python: 3.4 - env: DJANGO=1.4.20 + env: DJANGO=1.9a1 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 419adeb..eebe0ea 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,12 @@ Changelog ========= +* 2.2 (Not released) + * Added Python 3.5 support + * Added Django 1.9 support + * Removed Python 2.6 support + * Removed Django 1.4, 1.5, and 1.6 support + * 2.1.1 (August 10, 2015) * Added Polish locale * Fixed RemovedInDjango19Warning warnings From 0972a4bbe4f3187f7303cd9911b792dfaf85f6ed Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 24 Sep 2015 10:32:56 -0500 Subject: [PATCH 042/119] Remove load url from future --- avatar/templates/avatar/add.html | 1 - avatar/templates/avatar/change.html | 1 - avatar/templates/avatar/confirm_delete.html | 1 - avatar/templates/notification/avatar_friend_updated/full.txt | 2 +- avatar/templates/notification/avatar_friend_updated/notice.html | 2 +- 5 files changed, 2 insertions(+), 5 deletions(-) diff --git a/avatar/templates/avatar/add.html b/avatar/templates/avatar/add.html index 7a04b34..9b4fed6 100644 --- a/avatar/templates/avatar/add.html +++ b/avatar/templates/avatar/add.html @@ -1,6 +1,5 @@ {% extends "avatar/base.html" %} {% load i18n avatar_tags %} -{% load url from future %} {% block content %}

{% trans "Your current avatar: " %}

diff --git a/avatar/templates/avatar/change.html b/avatar/templates/avatar/change.html index 7e7b3d2..8d27359 100644 --- a/avatar/templates/avatar/change.html +++ b/avatar/templates/avatar/change.html @@ -1,6 +1,5 @@ {% extends "avatar/base.html" %} {% load i18n avatar_tags %} -{% load url from future %} {% block content %}

{% trans "Your current avatar: " %}

diff --git a/avatar/templates/avatar/confirm_delete.html b/avatar/templates/avatar/confirm_delete.html index 373131d..f81c815 100644 --- a/avatar/templates/avatar/confirm_delete.html +++ b/avatar/templates/avatar/confirm_delete.html @@ -1,6 +1,5 @@ {% extends "avatar/base.html" %} {% load i18n %} -{% load url from future %} {% block content %}

{% trans "Please select the avatars that you would like to delete." %}

diff --git a/avatar/templates/notification/avatar_friend_updated/full.txt b/avatar/templates/notification/avatar_friend_updated/full.txt index d5197a6..9510956 100644 --- a/avatar/templates/notification/avatar_friend_updated/full.txt +++ b/avatar/templates/notification/avatar_friend_updated/full.txt @@ -1,4 +1,4 @@ -{% load i18n %}{% load url from future %}{% blocktrans with user as avatar_creator and avatar.get_absolute_url as avatar_url %}{{ avatar_creator }} has updated their avatar {{ avatar }}. +{% load i18n %}{% blocktrans with user as avatar_creator and avatar.get_absolute_url as avatar_url %}{{ avatar_creator }} has updated their avatar {{ avatar }}. http://{{ current_site }}{{ avatar_url }} {% endblocktrans %} diff --git a/avatar/templates/notification/avatar_friend_updated/notice.html b/avatar/templates/notification/avatar_friend_updated/notice.html index c2ba8bc..79c5d54 100644 --- a/avatar/templates/notification/avatar_friend_updated/notice.html +++ b/avatar/templates/notification/avatar_friend_updated/notice.html @@ -1,2 +1,2 @@ -{% load i18n %}{% load url from future %}{% url 'profile_detail' username=user.username as user_url %}{# TODO: support custom user models via get_username; actually, is this template even used anymore? #} +{% load i18n %}{% url 'profile_detail' username=user.username as user_url %}{# TODO: support custom user models via get_username; actually, is this template even used anymore? #} {% blocktrans with user as avatar_creator and avatar.get_absolute_url as avatar_url %}{{ avatar_creator }} has updated their avatar {{ avatar }}.{% endblocktrans %} From bc6ae016ee832d708ab0a5428fc0f6e9af8cd077 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 24 Sep 2015 10:36:47 -0500 Subject: [PATCH 043/119] Revert coverage --- setup.py | 2 +- tests/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 718b35a..d6f7fe4 100644 --- a/setup.py +++ b/setup.py @@ -31,11 +31,11 @@ setup( 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', ], keywords='avatar, django', author='Eric Florenzano', diff --git a/tests/requirements.txt b/tests/requirements.txt index 054e173..824f13b 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,3 +1,3 @@ flake8 -coverage +coverage==3.7.1 django-discover-runner \ No newline at end of file From 1c44bd8d01b23d8a7d211ccdd6928342a14027fb Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 24 Sep 2015 10:46:49 -0500 Subject: [PATCH 044/119] Python 3.5 is not supported by Django 1.7 or 1.8 --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index a6242c7..58cfcca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,3 +20,7 @@ matrix: env: DJANGO=1.9a1 - python: 3.3 env: DJANGO=1.9a1 + - python: 3.5 + env: DJANGO=1.7.10 + - python: 3.5 + env: DJANGO=1.8.4 From 6db33fe977bc2497b2bbd0e962c369318cec65a0 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 24 Sep 2015 13:35:40 -0500 Subject: [PATCH 045/119] Remove strings in urls.py --- avatar/urls.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/avatar/urls.py b/avatar/urls.py index 3c6bec8..b4b19b1 100644 --- a/avatar/urls.py +++ b/avatar/urls.py @@ -4,11 +4,19 @@ except ImportError: # Django < 1.4 from django.conf.urls.defaults import patterns, url -urlpatterns = patterns('avatar.views', - url(r'^add/$', 'add', name='avatar_add'), - url(r'^change/$', 'change', name='avatar_change'), - url(r'^delete/$', 'delete', name='avatar_delete'), - url(r'^render_primary/(?P[\w\d\@\.\-_]{3,30})/(?P[\d]+)/$', 'render_primary', name='avatar_render_primary'), - url(r'^list/(?P[\+\w\@\.]+)/$', 'avatar_gallery', name='avatar_gallery'), - url(r'^list/(?P[\+\w\@\.]+)/(?P[\d]+)/$', 'avatar', name='avatar'), +from avatar import views + +urlpatterns = patterns('', + url(r'^add/$', views.add, name='avatar_add'), + url(r'^change/$', views.change, name='avatar_change'), + url(r'^delete/$', views.delete, name='avatar_delete'), + url(r'^render_primary/(?P[\w\d\@\.\-_]{3,30})/(?P[\d]+)/$', + views.render_primary, + name='avatar_render_primary'), + url(r'^list/(?P[\+\w\@\.]+)/$', + views.avatar_gallery, + name='avatar_gallery'), + url(r'^list/(?P[\+\w\@\.]+)/(?P[\d]+)/$', + views.avatar, + name='avatar'), ) From 884210b957d370a116b476f594823905b77a5b54 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 24 Sep 2015 13:41:12 -0500 Subject: [PATCH 046/119] Don't need south migrations anymore --- avatar/south_migrations/0001_initial.py | 72 ------------------------- avatar/south_migrations/__init__.py | 0 2 files changed, 72 deletions(-) delete mode 100644 avatar/south_migrations/0001_initial.py delete mode 100644 avatar/south_migrations/__init__.py diff --git a/avatar/south_migrations/0001_initial.py b/avatar/south_migrations/0001_initial.py deleted file mode 100644 index a0f58f0..0000000 --- a/avatar/south_migrations/0001_initial.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import SchemaMigration - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Adding model 'Avatar' - db.create_table('avatar_avatar', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), - ('primary', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('avatar', self.gf('django.db.models.fields.files.ImageField')(max_length=1024, blank=True)), - ('date_uploaded', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), - )) - db.send_create_signal('avatar', ['Avatar']) - - def backwards(self, orm): - # Deleting model 'Avatar' - db.delete_table('avatar_avatar') - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Group']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'user_set'", 'blank': 'True', 'to': "orm['auth.Permission']"}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'avatar.avatar': { - 'Meta': {'object_name': 'Avatar'}, - 'avatar': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}), - 'date_uploaded': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - } - } - - complete_apps = ['avatar'] diff --git a/avatar/south_migrations/__init__.py b/avatar/south_migrations/__init__.py deleted file mode 100644 index e69de29..0000000 From 09f91800b97327c012a9622d3705c1625cef69e5 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 24 Sep 2015 13:45:04 -0500 Subject: [PATCH 047/119] Remove branch coverage --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 62cf599..f21fa68 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ export PYTHONPATH=. test: flake8 avatar --ignore=E124,E501,E127,E128 - coverage run --branch --source=avatar `which django-admin.py` test tests + coverage run --source=avatar `which django-admin.py` test tests coverage report publish: clean From 1cad3fc8aa5f431c1a8ea3595f709a5b7309acff Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Fri, 23 Oct 2015 08:57:23 -0500 Subject: [PATCH 048/119] Update changelog, use Django 1.9b1 for tests --- .travis.yml | 4 ++-- CHANGELOG.rst | 1 + avatar/migrations/0002_add_user_primary_unique_together.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 58cfcca..ceacd40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,9 +17,9 @@ env: matrix: exclude: - python: 3.2 - env: DJANGO=1.9a1 + env: DJANGO=1.9b1 - python: 3.3 - env: DJANGO=1.9a1 + env: DJANGO=1.9b1 - python: 3.5 env: DJANGO=1.7.10 - python: 3.5 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index eebe0ea..3e44bcb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,7 @@ Changelog * Added Django 1.9 support * Removed Python 2.6 support * Removed Django 1.4, 1.5, and 1.6 support + * Added database-level enforcement of unique user/primary pair in Avatar model. * 2.1.1 (August 10, 2015) * Added Polish locale diff --git a/avatar/migrations/0002_add_user_primary_unique_together.py b/avatar/migrations/0002_add_user_primary_unique_together.py index c9bfb35..41fb958 100755 --- a/avatar/migrations/0002_add_user_primary_unique_together.py +++ b/avatar/migrations/0002_add_user_primary_unique_together.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.db import models, migrations +from django.db import migrations class Migration(migrations.Migration): From b14fe1624a3debb29f7592fe052c4f46c7e657c1 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Fri, 23 Oct 2015 09:08:19 -0500 Subject: [PATCH 049/119] Remove unnecessary try/except on import --- CHANGELOG.rst | 2 +- avatar/util.py | 17 ++--------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3e44bcb..f09625f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,9 +4,9 @@ Changelog * 2.2 (Not released) * Added Python 3.5 support * Added Django 1.9 support + * Added database-level enforcement of unique user/primary pair in Avatar model. * Removed Python 2.6 support * Removed Django 1.4, 1.5, and 1.6 support - * Added database-level enforcement of unique user/primary pair in Avatar model. * 2.1.1 (August 10, 2015) * Added Polish locale diff --git a/avatar/util.py b/avatar/util.py index 195bee6..d5aa6cc 100644 --- a/avatar/util.py +++ b/avatar/util.py @@ -9,17 +9,7 @@ try: except ImportError: force_bytes = str -try: - from django.contrib.auth import get_user_model -except ImportError: - from django.contrib.auth.models import User - - def get_user_model(): - return User - - custom_user_model = False -else: - custom_user_model = True +from django.contrib.auth import get_user_model from avatar.conf import settings @@ -37,10 +27,7 @@ def get_username(user): def get_user(username): """ Return user from a username/ish identifier """ - if custom_user_model: - return get_user_model().objects.get_by_natural_key(username) - else: - return get_user_model().objects.get(username=username) + return get_user_model().objects.get_by_natural_key(username) def get_cache_key(user_or_username, size, prefix): From a258377207c0f78af4296514ad08a9f1ac70f4a1 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Fri, 23 Oct 2015 09:33:10 -0500 Subject: [PATCH 050/119] Revert unique user/primary pair --- .coveragerc | 25 +++++++++++++++++++ CHANGELOG.rst | 1 - .../0002_add_user_primary_unique_together.py | 18 ------------- avatar/migrations/__init__.py | 21 ---------------- avatar/models.py | 1 - 5 files changed, 25 insertions(+), 41 deletions(-) create mode 100644 .coveragerc delete mode 100755 avatar/migrations/0002_add_user_primary_unique_together.py diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..b9917df --- /dev/null +++ b/.coveragerc @@ -0,0 +1,25 @@ +[report] +exclude_lines = + pragma: no cover + + # Don't complain about missing debug-only code: + def __repr__ + if self\.debug + + # Don't complain if tests don't hit defensive assertion code: + raise AssertionError + raise NotImplementedError + except ImportError + + # Don't complain if non-runnable code isn't run: + if 0: + if __name__ == .__main__.: + +omit = + avatar/*/migrations/* + +show_missing = True +precision = 2 + +[html] +directory = output/html/ diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f09625f..eebe0ea 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,7 +4,6 @@ Changelog * 2.2 (Not released) * Added Python 3.5 support * Added Django 1.9 support - * Added database-level enforcement of unique user/primary pair in Avatar model. * Removed Python 2.6 support * Removed Django 1.4, 1.5, and 1.6 support diff --git a/avatar/migrations/0002_add_user_primary_unique_together.py b/avatar/migrations/0002_add_user_primary_unique_together.py deleted file mode 100755 index 41fb958..0000000 --- a/avatar/migrations/0002_add_user_primary_unique_together.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('avatar', '0001_initial'), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='avatar', - unique_together=set([('user', 'primary')]), - ), - ] diff --git a/avatar/migrations/__init__.py b/avatar/migrations/__init__.py index 3b10179..e69de29 100644 --- a/avatar/migrations/__init__.py +++ b/avatar/migrations/__init__.py @@ -1,21 +0,0 @@ -""" -Django migrations for django-avatar app - -This package does not contain South migrations. South migrations can be found -in the ``south_migrations`` package. -""" - -SOUTH_ERROR_MESSAGE = """\n -For South support, customize the SOUTH_MIGRATION_MODULES setting like so: - - SOUTH_MIGRATION_MODULES = { - 'django-avatar': 'avatar.south_migrations', - } -""" - -# Ensure the user is not using Django 1.6 or below with South -try: - from django.db import migrations # noqa -except ImportError: - from django.core.exceptions import ImproperlyConfigured - raise ImproperlyConfigured(SOUTH_ERROR_MESSAGE) diff --git a/avatar/models.py b/avatar/models.py index e7127ff..1463df0 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -72,7 +72,6 @@ class Avatar(models.Model): class Meta: app_label = 'avatar' - unique_together = ('user', 'primary') def __unicode__(self): return _(six.u('Avatar for %s')) % self.user From 3aaea214b1b215afb1d8ee05545e9cf477d7657c Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Fri, 23 Oct 2015 09:40:17 -0500 Subject: [PATCH 051/119] Fix Travis Django 1.9 version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ceacd40..dc6898a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: make test env: - DJANGO=1.7.10 - DJANGO=1.8.4 - - DJANGO=1.9a1 + - DJANGO=1.9b1 matrix: exclude: - python: 3.2 From fd272e6bd722c37c0eefcb3dab3ab22f063fef99 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Wed, 25 Nov 2015 10:10:38 -0600 Subject: [PATCH 052/119] Update travis test parameters --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index dc6898a..c9072c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,15 +12,15 @@ install: script: make test env: - DJANGO=1.7.10 - - DJANGO=1.8.4 - - DJANGO=1.9b1 + - DJANGO=1.8.7 + - DJANGO=1.9rc2 matrix: exclude: - python: 3.2 - env: DJANGO=1.9b1 + env: DJANGO=1.9rc2 - python: 3.3 - env: DJANGO=1.9b1 + env: DJANGO=1.9rc2 - python: 3.5 env: DJANGO=1.7.10 - python: 3.5 - env: DJANGO=1.8.4 + env: DJANGO=1.8.7 From 295bfc4148e13b5601d3624ddcd7d980f078c11d Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Wed, 2 Dec 2015 09:58:46 -0600 Subject: [PATCH 053/119] Set version 2.2.0 --- .travis.yml | 6 +++--- CHANGELOG.rst | 2 +- avatar/__init__.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index c9072c7..0e5eedb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,13 +13,13 @@ script: make test env: - DJANGO=1.7.10 - DJANGO=1.8.7 - - DJANGO=1.9rc2 + - DJANGO=1.9 matrix: exclude: - python: 3.2 - env: DJANGO=1.9rc2 + env: DJANGO=1.9 - python: 3.3 - env: DJANGO=1.9rc2 + env: DJANGO=1.9 - python: 3.5 env: DJANGO=1.7.10 - python: 3.5 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index eebe0ea..f7ce89f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Changelog ========= -* 2.2 (Not released) +* 2.2.0 (December 2, 2015) * Added Python 3.5 support * Added Django 1.9 support * Removed Python 2.6 support diff --git a/avatar/__init__.py b/avatar/__init__.py index 55fa725..04188a1 100644 --- a/avatar/__init__.py +++ b/avatar/__init__.py @@ -1 +1 @@ -__version__ = '2.1.1' +__version__ = '2.2.0' From 6ac3e46a81056294240c37ae3401f7cba1d5c8b6 Mon Sep 17 00:00:00 2001 From: toogy Date: Mon, 17 Mar 2014 19:58:38 +0530 Subject: [PATCH 054/119] Adding the AVATAR_GRAVATAR_FIELD setting to define the user field used to get the gravatar email. --- avatar/conf.py | 1 + avatar/templatetags/avatar_tags.py | 4 ++-- docs/index.txt | 29 +++++++++++++++++------------ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/avatar/conf.py b/avatar/conf.py index 4d7f01f..2a74e25 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -9,6 +9,7 @@ class AvatarConf(AppConf): RESIZE_METHOD = Image.ANTIALIAS STORAGE_DIR = 'avatars' GRAVATAR_BASE_URL = 'https://www.gravatar.com/avatar/' + GRAVATAR_FIELD = 'email' GRAVATAR_BACKUP = True GRAVATAR_DEFAULT = None DEFAULT_URL = 'avatar/img/default.jpg' diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index 75a1a4f..6e2c6a5 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -31,8 +31,8 @@ def avatar_url(user, size=settings.AVATAR_DEFAULT_SIZE): params = {'s': str(size)} if settings.AVATAR_GRAVATAR_DEFAULT: params['d'] = settings.AVATAR_GRAVATAR_DEFAULT - path = "%s/?%s" % (hashlib.md5(force_bytes(user.email)).hexdigest(), - urlencode(params)) + path = "%s/?%s" % (hashlib.md5(force_bytes( + getattr(settings.GRAVATAR_FIELD))).hexdigest(), urlencode(params)) return urljoin(settings.AVATAR_GRAVATAR_BASE_URL, path) return get_default_avatar_url() diff --git a/docs/index.txt b/docs/index.txt index c16a9c4..43e2a4a 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -32,19 +32,19 @@ that are required. A minimal integration can work like this: 1. List this application in the ``INSTALLED_APPS`` portion of your settings file. Your settings file will look something like:: - + INSTALLED_APPS = ( # ... 'avatar', ) 2. Update your database:: - + python manage.py syncdb 3. Add the avatar urls to the end of your root urlconf. Your urlconf will look something like:: - + urlpatterns = patterns('', # ... (r'^avatar/', include('avatar.urls')), @@ -52,20 +52,20 @@ that are required. A minimal integration can work like this: 4. Somewhere in your template navigation scheme, link to the change avatar page:: - + Change your avatar 5. Wherever you want to display an avatar for a user, first load the avatar template tags:: - + {% load avatar_tags %} - + Then, use the ``avatar`` tag to display an avatar of a default size:: - + {% avatar user %} - + Or specify a size (in pixels) explicitly:: - + {% avatar user 65 %} Template tags and filter @@ -118,15 +118,20 @@ AVATAR_GRAVATAR_BACKUP True. AVATAR_GRAVATAR_DEFAULT - A string determining the style of the default Gravatar. Available options - listed in the - (Gravatar documentation)[https://en.gravatar.com/site/implement/images/#default-image]. + A string determining the style of the default Gravatar. Available options + listed in the + (Gravatar documentation)[https://en.gravatar.com/site/implement/images/#default-image]. Ex. 'retro'. Defaults to None. AVATAR_DEFAULT_URL The default URL to default to if ``AVATAR_GRAVATAR_BACKUP`` is set to False and there is no ``Avatar`` instance found in the system for the given user. +AVATAR_GRAVATAR_FIELD + The name of the user's field containing the gravatar email. Defaults to + ``email``. If you put, for example, ``gravatar``, django-avatar will get the + user's gravatar in ``user.gravatar``. + AVATAR_MAX_SIZE File size limit for avatar upload. Default is ``1024 * 1024`` (1mb). From 10c9e8af0daf4e6209ad2932c89bb75e418535df Mon Sep 17 00:00:00 2001 From: toogy Date: Mon, 17 Mar 2014 20:42:58 +0530 Subject: [PATCH 055/119] Fix GRAVATAR_FIELD > AVATAR_GRAVATAR_FIELD --- avatar/templatetags/avatar_tags.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index 6e2c6a5..9f3aac7 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -31,8 +31,9 @@ def avatar_url(user, size=settings.AVATAR_DEFAULT_SIZE): params = {'s': str(size)} if settings.AVATAR_GRAVATAR_DEFAULT: params['d'] = settings.AVATAR_GRAVATAR_DEFAULT - path = "%s/?%s" % (hashlib.md5(force_bytes( - getattr(settings.GRAVATAR_FIELD))).hexdigest(), urlencode(params)) + path = "%s/?%s" % (hashlib.md5( + force_bytes(getattr(settings.AVATAR_GRAVATAR_FIELD))).hexdigest(), + urlencode(params)) return urljoin(settings.AVATAR_GRAVATAR_BASE_URL, path) return get_default_avatar_url() From d182c83e0f1b023102fca1940d2025a7211e3103 Mon Sep 17 00:00:00 2001 From: toogy Date: Mon, 17 Mar 2014 22:33:26 +0530 Subject: [PATCH 056/119] Fixing getattr --- avatar/templatetags/avatar_tags.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index 9f3aac7..e59c068 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -31,9 +31,8 @@ def avatar_url(user, size=settings.AVATAR_DEFAULT_SIZE): params = {'s': str(size)} if settings.AVATAR_GRAVATAR_DEFAULT: params['d'] = settings.AVATAR_GRAVATAR_DEFAULT - path = "%s/?%s" % (hashlib.md5( - force_bytes(getattr(settings.AVATAR_GRAVATAR_FIELD))).hexdigest(), - urlencode(params)) + path = "%s/?%s" % (hashlib.md5(force_bytes(getattr(user, + settings.AVATAR_GRAVATAR_FIELD))).hexdigest(), urlencode(params)) return urljoin(settings.AVATAR_GRAVATAR_BASE_URL, path) return get_default_avatar_url() From c9c18733822e9869133131ccec9a6ad173e10327 Mon Sep 17 00:00:00 2001 From: Victor Kotseruba Date: Mon, 21 Dec 2015 19:44:43 +0800 Subject: [PATCH 057/119] facebook backup --- avatar/conf.py | 2 ++ avatar/templatetags/avatar_tags.py | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/avatar/conf.py b/avatar/conf.py index 14a263a..30b05a1 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -24,6 +24,8 @@ class AvatarConf(AppConf): STORAGE = settings.DEFAULT_FILE_STORAGE CLEANUP_DELETED = False AUTO_GENERATE_SIZES = (DEFAULT_SIZE,) + FACEBOOK_BACKUP = False + FACEBOOK_GET_ID = None def configure_auto_generate_avatar_sizes(self, value): return value or getattr(settings, 'AVATAR_AUTO_GENERATE_SIZES', diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index 75a1a4f..fdb3a5e 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -11,6 +11,7 @@ from django.core.urlresolvers import reverse from django.template.loader import render_to_string from django.utils import six from django.utils.translation import ugettext as _ +from django.utils.module_loading import import_string from avatar.conf import settings from avatar.util import (get_primary_avatar, get_default_avatar_url, @@ -19,6 +20,14 @@ from avatar.models import Avatar register = template.Library() +get_facebook_id = None + +if settings.AVATAR_FACEBOOK_BACKUP: + if callable(settings.AVATAR_FACEBOOK_GET_ID): + get_facebook_id = settings.AVATAR_FACEBOOK_GET_ID + else: + get_facebook_id = import_string(settings.AVATAR_FACEBOOK_GET_ID) + @cache_result() @register.simple_tag @@ -27,6 +36,13 @@ def avatar_url(user, size=settings.AVATAR_DEFAULT_SIZE): if avatar: return avatar.avatar_url(size) + if settings.AVATAR_FACEBOOK_BACKUP: + fb_id = get_facebook_id(user) + if fb_id: + return 'https://graph.facebook.com/{fb_id}/picture?type=square&width={size}&height={size}'.format( + fb_id=fb_id, size=size + ) + if settings.AVATAR_GRAVATAR_BACKUP: params = {'s': str(size)} if settings.AVATAR_GRAVATAR_DEFAULT: From 55c27f7f736b7fba78245c8022b56a2ebdb04b0d Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 21 Dec 2015 16:35:28 -0600 Subject: [PATCH 058/119] Update changelog with new feature --- CHANGELOG.rst | 3 +++ docs/index.txt | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f7ce89f..beaac79 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,9 @@ Changelog ========= +* 2.2.1 (Not released) + * Added AVATAR_GRAVATAR_FIELD setting to define the user field to get the gravatar email. + * 2.2.0 (December 2, 2015) * Added Python 3.5 support * Added Django 1.9 support diff --git a/docs/index.txt b/docs/index.txt index 43e2a4a..021a387 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -128,9 +128,9 @@ AVATAR_DEFAULT_URL and there is no ``Avatar`` instance found in the system for the given user. AVATAR_GRAVATAR_FIELD - The name of the user's field containing the gravatar email. Defaults to - ``email``. If you put, for example, ``gravatar``, django-avatar will get the - user's gravatar in ``user.gravatar``. + The name of the user's field containing the gravatar email. For example, if you set + this to ``gravatar`` then django-avatar will get the user's gravatar in ``user.gravatar``. + Defaults to ``email``. AVATAR_MAX_SIZE File size limit for avatar upload. Default is ``1024 * 1024`` (1mb). From 4fd5c60a3252171f71e5a64c1edf7184d248c797 Mon Sep 17 00:00:00 2001 From: Johannes Wilm Date: Sun, 3 Jan 2016 16:06:05 +0100 Subject: [PATCH 059/119] fix two errors in Brazilian translation file --- avatar/locale/pt_BR/LC_MESSAGES/django.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avatar/locale/pt_BR/LC_MESSAGES/django.po b/avatar/locale/pt_BR/LC_MESSAGES/django.po index e70e1dc..1a43c63 100644 --- a/avatar/locale/pt_BR/LC_MESSAGES/django.po +++ b/avatar/locale/pt_BR/LC_MESSAGES/django.po @@ -22,7 +22,7 @@ msgid "" "%(ext)s is an invalid file extension. Authorized extensions are : %" "(valid_exts_list)s" msgstr "Extensão informada inválida. Os Formatos permitidos são : %" - +"(valid_exts_list)s" #: forms.py:38 #, python-format msgid "" @@ -37,7 +37,7 @@ msgid "" "You already have %(nb_avatars)d avatars, and the maximum allowed is %" "(nb_max_avatars)d." msgstr "Você já possui %(nb_avatars)d fotos. O máximo permitido é %" - +"(nb_max_avatars)d." #: forms.py:56 forms.py:67 msgid "Choices" msgstr "Opções" From 7a1435557f469c6b4bb1a8c6a587cb0d28c4c8e9 Mon Sep 17 00:00:00 2001 From: Johannes Wilm Date: Sun, 3 Jan 2016 16:08:31 +0100 Subject: [PATCH 060/119] one fix errors in Brazilian translation file --- avatar/locale/pt_BR/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avatar/locale/pt_BR/LC_MESSAGES/django.po b/avatar/locale/pt_BR/LC_MESSAGES/django.po index 1a43c63..aad3f83 100644 --- a/avatar/locale/pt_BR/LC_MESSAGES/django.po +++ b/avatar/locale/pt_BR/LC_MESSAGES/django.po @@ -21,7 +21,7 @@ msgstr "" msgid "" "%(ext)s is an invalid file extension. Authorized extensions are : %" "(valid_exts_list)s" -msgstr "Extensão informada inválida. Os Formatos permitidos são : %" +msgstr "%(ext)s é uma extensão informada inválida. Os Formatos permitidos são : %" "(valid_exts_list)s" #: forms.py:38 #, python-format From af45e43c46a22f3168ab946bf914a45eae9ade19 Mon Sep 17 00:00:00 2001 From: Johannes Wilm Date: Sun, 3 Jan 2016 16:10:24 +0100 Subject: [PATCH 061/119] Remove replace urlpatterns with simple array, make compatible with Django 1.9 --- avatar/urls.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/avatar/urls.py b/avatar/urls.py index b4b19b1..623e252 100644 --- a/avatar/urls.py +++ b/avatar/urls.py @@ -2,11 +2,11 @@ try: from django.conf.urls import patterns, url except ImportError: # Django < 1.4 - from django.conf.urls.defaults import patterns, url + from django.conf.urls.defaults import url from avatar import views -urlpatterns = patterns('', +urlpatterns = [ url(r'^add/$', views.add, name='avatar_add'), url(r'^change/$', views.change, name='avatar_change'), url(r'^delete/$', views.delete, name='avatar_delete'), @@ -19,4 +19,4 @@ urlpatterns = patterns('', url(r'^list/(?P[\+\w\@\.]+)/(?P[\d]+)/$', views.avatar, name='avatar'), -) +] From 6b1aa840f8279a160ca7499e2404adf84642974b Mon Sep 17 00:00:00 2001 From: Johannes Wilm Date: Mon, 4 Jan 2016 16:15:30 +0100 Subject: [PATCH 062/119] remove patterns import --- avatar/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avatar/urls.py b/avatar/urls.py index 623e252..2608787 100644 --- a/avatar/urls.py +++ b/avatar/urls.py @@ -1,5 +1,5 @@ try: - from django.conf.urls import patterns, url + from django.conf.urls import url except ImportError: # Django < 1.4 from django.conf.urls.defaults import url From 1a2c5e79abeef35e40bb0cfe2526149e4b198d6b Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 4 Jan 2016 09:40:06 -0600 Subject: [PATCH 063/119] Update release notes --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index beaac79..0ed68a7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,8 @@ Changelog * 2.2.1 (Not released) * Added AVATAR_GRAVATAR_FIELD setting to define the user field to get the gravatar email. + * Improved Django 1.9/1.10 compability + * Improved Brazilian translations * 2.2.0 (December 2, 2015) * Added Python 3.5 support From a292ad06cb39b46440fb019d3ffbcd15a3144231 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 11 Jan 2016 23:01:06 -0600 Subject: [PATCH 064/119] Set version 2.2.1 --- CHANGELOG.rst | 2 +- avatar/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0ed68a7..51bff15 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Changelog ========= -* 2.2.1 (Not released) +* 2.2.1 (January 11, 2016) * Added AVATAR_GRAVATAR_FIELD setting to define the user field to get the gravatar email. * Improved Django 1.9/1.10 compability * Improved Brazilian translations diff --git a/avatar/__init__.py b/avatar/__init__.py index 04188a1..36a511e 100644 --- a/avatar/__init__.py +++ b/avatar/__init__.py @@ -1 +1 @@ -__version__ = '2.2.0' +__version__ = '2.2.1' From a8c6f4e73a6eacba97757783034d81e634be078f Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 11 Jan 2016 23:03:05 -0600 Subject: [PATCH 065/119] Update Travis Django versions --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0e5eedb..6287760 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,15 +12,15 @@ install: script: make test env: - DJANGO=1.7.10 - - DJANGO=1.8.7 - - DJANGO=1.9 + - DJANGO=1.8.8 + - DJANGO=1.9.1 matrix: exclude: - python: 3.2 - env: DJANGO=1.9 + env: DJANGO=1.9.1 - python: 3.3 - env: DJANGO=1.9 + env: DJANGO=1.9.1 - python: 3.5 env: DJANGO=1.7.10 - python: 3.5 - env: DJANGO=1.8.7 + env: DJANGO=1.8.8 From f14e97ae3fbcb486ace593abda979c043224fe74 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 11 Jan 2016 23:05:03 -0600 Subject: [PATCH 066/119] Add badges --- README.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.rst b/README.rst index 4606cd8..1ad0e42 100644 --- a/README.rst +++ b/README.rst @@ -2,6 +2,13 @@ django-avatar ============= +.. image:: https://badge.fury.io/py/django-avatar.svg + :target: https://badge.fury.io/py/django-avatar + +.. image:: https://readthedocs.org/projects/django-avatar/badge/?version=latest + :target: http://django-avatar.readthedocs.org/en/latest/?badge=latest + :alt: Documentation Status + .. image:: https://travis-ci.org/grantmcconnaughey/django-avatar.svg :target: https://travis-ci.org/grantmcconnaughey/django-avatar From dd743d452549a57c4664ca0be941cf0255326160 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 11 Jan 2016 23:06:53 -0600 Subject: [PATCH 067/119] Start tracking test coverage --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6287760..7a04e5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ python: - 3.3 - 3.4 - 3.5 +before_install: + - pip install coveralls install: - pip install -e . - pip install -r tests/requirements.txt @@ -24,3 +26,5 @@ matrix: env: DJANGO=1.7.10 - python: 3.5 env: DJANGO=1.8.8 +after_success: + - coveralls From f6f8952510a40e52cf5a8c7eea9c0aea27478b8c Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Mon, 11 Jan 2016 23:15:58 -0600 Subject: [PATCH 068/119] Add coverage badge --- README.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.rst b/README.rst index 1ad0e42..6188ca5 100644 --- a/README.rst +++ b/README.rst @@ -12,6 +12,9 @@ django-avatar .. image:: https://travis-ci.org/grantmcconnaughey/django-avatar.svg :target: https://travis-ci.org/grantmcconnaughey/django-avatar +.. image:: https://coveralls.io/repos/grantmcconnaughey/django-avatar/badge.svg?branch=master&service=github + :target: https://coveralls.io/github/grantmcconnaughey/django-avatar?branch=master + Django-avatar is a reusable application for handling user avatars. It has the ability to default to Gravatar if no avatar is found for a certain user. Django-avatar automatically generates thumbnails and stores them to your default From 724a4787381d227fe26b9a93bad0145b7f51aada Mon Sep 17 00:00:00 2001 From: Victor Kotseruba Date: Mon, 18 Jan 2016 18:14:15 +0800 Subject: [PATCH 069/119] disable cache option --- avatar/conf.py | 1 + avatar/util.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/avatar/conf.py b/avatar/conf.py index 30b05a1..6c5d5c2 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -26,6 +26,7 @@ class AvatarConf(AppConf): AUTO_GENERATE_SIZES = (DEFAULT_SIZE,) FACEBOOK_BACKUP = False FACEBOOK_GET_ID = None + DISABLE_CACHE = False def configure_auto_generate_avatar_sizes(self, value): return value or getattr(settings, 'AVATAR_AUTO_GENERATE_SIZES', diff --git a/avatar/util.py b/avatar/util.py index 195bee6..2a14121 100644 --- a/avatar/util.py +++ b/avatar/util.py @@ -64,6 +64,12 @@ def cache_result(default_size=settings.AVATAR_DEFAULT_SIZE): Decorator to cache the result of functions that take a ``user`` and a ``size`` value. """ + + if settings.AVATAR_DISABLE_CACHE: + def decorator(func): + return func + return decorator + def decorator(func): def cached_func(user, size=None): prefix = func.__name__ From 0aaa59e0a775e6d5a3b90decbe9dbba0bf0e9877 Mon Sep 17 00:00:00 2001 From: Victor Kotseruba Date: Mon, 18 Jan 2016 18:57:41 +0800 Subject: [PATCH 070/119] RANDOMIZE_HASHES option --- avatar/conf.py | 1 + avatar/models.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/avatar/conf.py b/avatar/conf.py index 6c5d5c2..4e81b63 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -27,6 +27,7 @@ class AvatarConf(AppConf): FACEBOOK_BACKUP = False FACEBOOK_GET_ID = None DISABLE_CACHE = False + RANDOMIZE_HASHES = False def configure_auto_generate_avatar_sizes(self, value): return value or getattr(settings, 'AVATAR_AUTO_GENERATE_SIZES', diff --git a/avatar/models.py b/avatar/models.py index bca0918..bc29b83 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -1,3 +1,4 @@ +import binascii import datetime import os import hashlib @@ -47,7 +48,10 @@ def avatar_file_path(instance=None, filename=None, size=None, ext=None): # File doesn't exist yet if settings.AVATAR_HASH_FILENAMES: (root, ext) = os.path.splitext(filename) - filename = hashlib.md5(force_bytes(filename)).hexdigest() + if settings.AVATAR_RANDOMIZE_HASHES: + filename = binascii.hexlify(os.urandom(16)).decode('ascii') + else: + filename = hashlib.md5(force_bytes(filename)).hexdigest() filename = filename + ext if size: tmppath.extend(['resized', str(size)]) From 16abb5d50b60307baad8416ddeaacdb961bc6a46 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Tue, 19 Jan 2016 10:00:34 -0600 Subject: [PATCH 071/119] Update tests, invalidate cache after changing avatar --- .coveragerc | 2 +- .gitignore | 3 ++- README.rst | 2 +- avatar/urls.py | 6 +---- avatar/views.py | 3 ++- tests/tests.py | 61 ++++++++++++++++++++++++++++++++++--------------- 6 files changed, 49 insertions(+), 28 deletions(-) diff --git a/.coveragerc b/.coveragerc index b9917df..67ec35c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -22,4 +22,4 @@ show_missing = True precision = 2 [html] -directory = output/html/ +directory = htmlcov/ diff --git a/.gitignore b/.gitignore index bd654af..085aa08 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ dist/ *.egg-info/ avatars .coverage -docs/_build \ No newline at end of file +docs/_build +htmlcov/ diff --git a/README.rst b/README.rst index 6188ca5..7b97236 100644 --- a/README.rst +++ b/README.rst @@ -13,7 +13,7 @@ django-avatar :target: https://travis-ci.org/grantmcconnaughey/django-avatar .. image:: https://coveralls.io/repos/grantmcconnaughey/django-avatar/badge.svg?branch=master&service=github - :target: https://coveralls.io/github/grantmcconnaughey/django-avatar?branch=master + :target: https://coveralls.io/github/grantmcconnaughey/django-avatar?branch=master Django-avatar is a reusable application for handling user avatars. It has the ability to default to Gravatar if no avatar is found for a certain user. diff --git a/avatar/urls.py b/avatar/urls.py index 2608787..02a9981 100644 --- a/avatar/urls.py +++ b/avatar/urls.py @@ -1,8 +1,4 @@ -try: - from django.conf.urls import url -except ImportError: - # Django < 1.4 - from django.conf.urls.defaults import url +from django.conf.urls import url from avatar import views diff --git a/avatar/views.py b/avatar/views.py index 90341ec..24d6b34 100644 --- a/avatar/views.py +++ b/avatar/views.py @@ -11,7 +11,7 @@ from avatar.forms import PrimaryAvatarForm, DeleteAvatarForm, UploadAvatarForm from avatar.models import Avatar from avatar.signals import avatar_updated from avatar.util import (get_primary_avatar, get_default_avatar_url, - get_user_model, get_user) + get_user_model, get_user, invalidate_cache) def _get_next(request): @@ -107,6 +107,7 @@ def change(request, extra_context=None, next_override=None, avatar.primary = True avatar.save() updated = True + invalidate_cache(request.user) messages.success(request, _("Successfully updated your avatar.")) if updated: avatar_updated.send(sender=Avatar, user=request.user, avatar=avatar) diff --git a/tests/tests.py b/tests/tests.py index 73d89af..64db82b 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -30,9 +30,9 @@ class AvatarTests(TestCase): self.site = AdminSite() Image.init() - def testAdminGetAvatarReturnsDifferentImageTags(self): - self.testNormalImageUpload() - self.testNormalImageUpload() + def test_admin_get_avatar_returns_different_image_tags(self): + self.test_normal_image_upload() + self.test_normal_image_upload() primary = Avatar.objects.get(primary=True) old = Avatar.objects.get(primary=False) @@ -42,41 +42,43 @@ class AvatarTests(TestCase): self.assertNotEqual(primary_link, old_link) - def testNonImageUpload(self): + def test_non_image_upload(self): response = upload_helper(self, "nonimagefile") self.assertEqual(response.status_code, 200) self.assertNotEqual(response.context['upload_avatar_form'].errors, {}) - def testNormalImageUpload(self): + def test_normal_image_upload(self): response = upload_helper(self, "test.png") self.assertEqual(response.status_code, 200) self.assertEqual(len(response.redirect_chain), 1) self.assertEqual(response.context['upload_avatar_form'].errors, {}) avatar = get_primary_avatar(self.user) - self.assertNotEqual(avatar, None) + self.assertIsNotNone(avatar) + self.assertEqual(avatar.user, self.user) + self.assertTrue(avatar.primary) - def testImageWithoutExtension(self): + def test_image_without_wrong_extension(self): # use with AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png') response = upload_helper(self, "imagefilewithoutext") self.assertEqual(response.status_code, 200) self.assertEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.assertNotEqual(response.context['upload_avatar_form'].errors, {}) - def testImageWithWrongExtension(self): + def test_image_with_wrong_extension(self): # use with AVATAR_ALLOWED_FILE_EXTS = ('.jpg', '.png') response = upload_helper(self, "imagefilewithwrongext.ogg") self.assertEqual(response.status_code, 200) self.assertEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.assertNotEqual(response.context['upload_avatar_form'].errors, {}) - def testImageTooBig(self): + def test_image_too_big(self): # use with AVATAR_MAX_SIZE = 1024 * 1024 response = upload_helper(self, "testbig.png") self.assertEqual(response.status_code, 200) self.assertEqual(len(response.redirect_chain), 0) # Redirect only if it worked self.assertNotEqual(response.context['upload_avatar_form'].errors, {}) - def testDefaultUrl(self): + def test_default_url(self): response = self.client.get(reverse('avatar_render_primary', kwargs={ 'user': self.user.username, 'size': 80, @@ -88,18 +90,18 @@ class AvatarTests(TestCase): self.assertTrue(base_url in loc) self.assertTrue(loc.endswith(settings.AVATAR_DEFAULT_URL)) - def testNonExistingUser(self): + def test_non_existing_user(self): a = get_primary_avatar("nonexistinguser") self.assertEqual(a, None) - def testThereCanBeOnlyOnePrimaryAvatar(self): + def test_there_can_be_only_one_primary_avatar(self): for i in range(1, 10): - self.testNormalImageUpload() + self.test_normal_image_upload() count = Avatar.objects.filter(user=self.user, primary=True).count() self.assertEqual(count, 1) - def testDeleteAvatar(self): - self.testNormalImageUpload() + def test_delete_avatar(self): + self.test_normal_image_upload() avatar = Avatar.objects.filter(user=self.user) self.assertEqual(len(avatar), 1) response = self.client.post(reverse('avatar_delete'), { @@ -110,8 +112,8 @@ class AvatarTests(TestCase): count = Avatar.objects.filter(user=self.user).count() self.assertEqual(count, 0) - def testDeletePrimaryAvatarAndNewPrimary(self): - self.testThereCanBeOnlyOnePrimaryAvatar() + def test_delete_primary_avatar_and_new_primary(self): + self.test_there_can_be_only_one_primary_avatar() primary = get_primary_avatar(self.user) oid = primary.id self.client.post(reverse('avatar_delete'), { @@ -123,9 +125,30 @@ class AvatarTests(TestCase): avatars = Avatar.objects.filter(user=self.user) self.assertEqual(avatars[0].id, primaries[0].id) - def testTooManyAvatars(self): + def test_change_avatar_get(self): + self.test_normal_image_upload() + response = self.client.get(reverse('avatar_change')) + + self.assertEqual(response.status_code, 200) + self.assertIsNotNone(response.context['avatar']) + + def test_change_avatar_post_updates_primary_avatar(self): + self.test_there_can_be_only_one_primary_avatar() + old_primary = Avatar.objects.get(user=self.user, primary=True) + choice = Avatar.objects.filter(user=self.user, primary=False)[0] + response = self.client.post(reverse('avatar_change'), { + 'choice': choice.pk, + }) + + self.assertEqual(response.status_code, 302) + new_primary = Avatar.objects.get(user=self.user, primary=True) + self.assertEqual(new_primary.pk, choice.pk) + # Avatar with old primary pk exists but it is not primary anymore + self.assertTrue(Avatar.objects.filter(user=self.user, pk=old_primary.pk, primary=False).exists()) + + def test_too_many_avatars(self): for i in range(0, settings.AVATAR_MAX_AVATARS_PER_USER): - self.testNormalImageUpload() + self.test_normal_image_upload() count_before = Avatar.objects.filter(user=self.user).count() response = upload_helper(self, "test.png") count_after = Avatar.objects.filter(user=self.user).count() From a67ba8fe32dcc55b795df46e0641d022666bfb02 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Tue, 19 Jan 2016 10:05:18 -0600 Subject: [PATCH 072/119] Update documentation --- docs/index.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/index.txt b/docs/index.txt index 021a387..a22cfd1 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -38,17 +38,17 @@ that are required. A minimal integration can work like this: 'avatar', ) -2. Update your database:: +2. Migrate your database:: - python manage.py syncdb + python manage.py migrate 3. Add the avatar urls to the end of your root urlconf. Your urlconf will look something like:: - urlpatterns = patterns('', + urlpatterns = [ # ... (r'^avatar/', include('avatar.urls')), - ) + ] 4. Somewhere in your template navigation scheme, link to the change avatar page:: @@ -72,7 +72,7 @@ Template tags and filter ------------------------ To begin using these template tags, you must first load the tags into the -template rendering system: +template rendering system:: {% load avatar_tags %} @@ -120,7 +120,7 @@ AVATAR_GRAVATAR_BACKUP AVATAR_GRAVATAR_DEFAULT A string determining the style of the default Gravatar. Available options listed in the - (Gravatar documentation)[https://en.gravatar.com/site/implement/images/#default-image]. + `Gravatar documentation `_. Ex. 'retro'. Defaults to None. AVATAR_DEFAULT_URL From 86a1e59a4dccc6266bb2440cd413ab4ade40b46c Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Tue, 19 Jan 2016 10:12:28 -0600 Subject: [PATCH 073/119] Remove unused views --- avatar/templates/avatar/avatar.html | 10 ----- avatar/templates/avatar/gallery.html | 10 ----- avatar/urls.py | 6 --- avatar/views.py | 62 +--------------------------- 4 files changed, 1 insertion(+), 87 deletions(-) delete mode 100644 avatar/templates/avatar/avatar.html delete mode 100644 avatar/templates/avatar/gallery.html diff --git a/avatar/templates/avatar/avatar.html b/avatar/templates/avatar/avatar.html deleted file mode 100644 index 6346d96..0000000 --- a/avatar/templates/avatar/avatar.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - <!-- Insert your title here --> - - - - - diff --git a/avatar/templates/avatar/gallery.html b/avatar/templates/avatar/gallery.html deleted file mode 100644 index 6346d96..0000000 --- a/avatar/templates/avatar/gallery.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - <!-- Insert your title here --> - - - - - diff --git a/avatar/urls.py b/avatar/urls.py index 02a9981..edb684a 100644 --- a/avatar/urls.py +++ b/avatar/urls.py @@ -9,10 +9,4 @@ urlpatterns = [ url(r'^render_primary/(?P[\w\d\@\.\-_]{3,30})/(?P[\d]+)/$', views.render_primary, name='avatar_render_primary'), - url(r'^list/(?P[\+\w\@\.]+)/$', - views.avatar_gallery, - name='avatar_gallery'), - url(r'^list/(?P[\+\w\@\.]+)/(?P[\d]+)/$', - views.avatar, - name='avatar'), ] diff --git a/avatar/views.py b/avatar/views.py index 24d6b34..18ead7c 100644 --- a/avatar/views.py +++ b/avatar/views.py @@ -1,4 +1,3 @@ -from django.http import Http404 from django.shortcuts import render, redirect from django.utils import six from django.utils.translation import ugettext as _ @@ -11,7 +10,7 @@ from avatar.forms import PrimaryAvatarForm, DeleteAvatarForm, UploadAvatarForm from avatar.models import Avatar from avatar.signals import avatar_updated from avatar.util import (get_primary_avatar, get_default_avatar_url, - get_user_model, get_user, invalidate_cache) + invalidate_cache) def _get_next(request): @@ -160,65 +159,6 @@ def delete(request, extra_context=None, next_override=None, *args, **kwargs): return render(request, 'avatar/confirm_delete.html', context) -def avatar_gallery(request, username, template_name="avatar/gallery.html"): - try: - user = get_user(username) - except get_user_model().DoesNotExist: - raise Http404 - - context = { - "other_user": user, - "avatars": user.avatar_set.all(), - } - - return render(request, template_name, context) - - -def avatar(request, username, id, template_name="avatar/avatar.html"): - try: - user = get_user(username) - except get_user_model().DoesNotExist: - raise Http404 - avatars = user.avatar_set.order_by("-date_uploaded") - index = None - avatar = None - if avatars: - avatar = avatars.get(pk=id) - if not avatar: - return Http404 - - index = avatars.filter(date_uploaded__gt=avatar.date_uploaded).count() - count = avatars.count() - - if index == 0: - prev = avatars.reverse()[0] - if count <= 1: - next = avatars[0] - else: - next = avatars[1] - else: - prev = avatars[index - 1] - - if (index + 1) >= count: - next = avatars[0] - prev_index = index - 1 - if prev_index < 0: - prev_index = 0 - prev = avatars[prev_index] - else: - next = avatars[index + 1] - - return render(request, template_name, { - "other_user": user, - "avatar": avatar, - "index": index + 1, - "avatars": avatars, - "next": next, - "prev": prev, - "count": count, - }) - - def render_primary(request, user=None, size=settings.AVATAR_DEFAULT_SIZE): size = int(size) avatar = get_primary_avatar(user, size=size) From de25cfb8c6617f9c3937c68df1ff7e28b950ffe5 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Tue, 19 Jan 2016 10:13:46 -0600 Subject: [PATCH 074/119] Update changelog --- CHANGELOG.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 51bff15..c9f8c2e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,9 @@ Changelog ========= +* 2.2.2 (Not released): + * Fixed issue where cache was not invalidated after updating avatar + * 2.2.1 (January 11, 2016) * Added AVATAR_GRAVATAR_FIELD setting to define the user field to get the gravatar email. * Improved Django 1.9/1.10 compability From cdb797405495053871ad00c04c05721c8b78c154 Mon Sep 17 00:00:00 2001 From: Kaspars Sprogis Date: Mon, 8 Feb 2016 22:01:12 +0200 Subject: [PATCH 075/119] New setting to specify path to a method for avatar file path handling. Solves problems related to custom deployments and directory paths: #10 #9. --- avatar/conf.py | 1 + avatar/models.py | 6 ++++-- docs/index.txt | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/avatar/conf.py b/avatar/conf.py index 2a74e25..de814fd 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -8,6 +8,7 @@ class AvatarConf(AppConf): DEFAULT_SIZE = 80 RESIZE_METHOD = Image.ANTIALIAS STORAGE_DIR = 'avatars' + PATH_HANDLER = 'avatar.models.avatar_path_handler' GRAVATAR_BASE_URL = 'https://www.gravatar.com/avatar/' GRAVATAR_FIELD = 'email' GRAVATAR_BACKUP = True diff --git a/avatar/models.py b/avatar/models.py index 1463df0..facfb07 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -7,6 +7,7 @@ from django.db import models from django.core.files import File from django.core.files.base import ContentFile from django.core.files.storage import get_storage_class +from django.utils.module_loading import import_string from django.utils.translation import ugettext as _ from django.utils import six from django.db.models import signals @@ -22,8 +23,7 @@ except ImportError: avatar_storage = get_storage_class(settings.AVATAR_STORAGE)() - -def avatar_file_path(instance=None, filename=None, size=None, ext=None): +def avatar_path_handler(instance=None, filename=None, size=None, ext=None): tmppath = [settings.AVATAR_STORAGE_DIR] if settings.AVATAR_HASH_USERDIRNAMES: tmp = hashlib.md5(get_username(instance.user)).hexdigest() @@ -51,6 +51,8 @@ def avatar_file_path(instance=None, filename=None, size=None, ext=None): tmppath.append(os.path.basename(filename)) return os.path.join(*tmppath) +avatar_file_path = import_string(settings.AVATAR_PATH_HANDLER) + def find_extension(format): format = format.lower() diff --git a/docs/index.txt b/docs/index.txt index a22cfd1..96f8b5c 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -135,6 +135,10 @@ AVATAR_GRAVATAR_FIELD AVATAR_MAX_SIZE File size limit for avatar upload. Default is ``1024 * 1024`` (1mb). +AVATAR_PATH_HANDLER + Path to a method for avatar file path handling. Default is + ``avatar.models.avatar_path_handler``. + Management Commands ------------------- From c2a5cec2bf6efbe9966431f095d4cfaf2fb62789 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Tue, 9 Feb 2016 09:06:16 -0600 Subject: [PATCH 076/119] Added documentation for new settings --- CHANGELOG.rst | 6 ++- avatar/conf.py | 2 +- avatar/models.py | 1 + avatar/templatetags/avatar_tags.py | 14 +++--- avatar/util.py | 2 +- docs/index.txt | 75 +++++++++++++++++++----------- 6 files changed, 63 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c9f8c2e..7b54037 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,8 +1,12 @@ Changelog ========= -* 2.2.2 (Not released): +* 3.0 (Not released): + * Added the ability to hide usernames/emails from avatar URLs. + * Added the ability to use a Facebook Graph avatar as a backup. + * Added a setting to disable the avatar cache. * Fixed issue where cache was not invalidated after updating avatar + * Renamed the ``avatar.util`` module to ``avatar.utils``. * 2.2.1 (January 11, 2016) * Added AVATAR_GRAVATAR_FIELD setting to define the user field to get the gravatar email. diff --git a/avatar/conf.py b/avatar/conf.py index 36696dc..05e36af 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -28,7 +28,7 @@ class AvatarConf(AppConf): AUTO_GENERATE_SIZES = (DEFAULT_SIZE,) FACEBOOK_BACKUP = False FACEBOOK_GET_ID = None - DISABLE_CACHE = False + CACHE_ENABLED = True RANDOMIZE_HASHES = False def configure_auto_generate_avatar_sizes(self, value): diff --git a/avatar/models.py b/avatar/models.py index 5a95c04..3557410 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -25,6 +25,7 @@ except ImportError: avatar_storage = get_storage_class(settings.AVATAR_STORAGE)() + def avatar_path_handler(instance=None, filename=None, size=None, ext=None): tmppath = [settings.AVATAR_STORAGE_DIR] if settings.AVATAR_HASH_USERDIRNAMES: diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index e8fb28e..651c8d3 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -36,13 +36,6 @@ def avatar_url(user, size=settings.AVATAR_DEFAULT_SIZE): if avatar: return avatar.avatar_url(size) - if settings.AVATAR_FACEBOOK_BACKUP: - fb_id = get_facebook_id(user) - if fb_id: - return 'https://graph.facebook.com/{fb_id}/picture?type=square&width={size}&height={size}'.format( - fb_id=fb_id, size=size - ) - if settings.AVATAR_GRAVATAR_BACKUP: params = {'s': str(size)} if settings.AVATAR_GRAVATAR_DEFAULT: @@ -51,6 +44,13 @@ def avatar_url(user, size=settings.AVATAR_DEFAULT_SIZE): settings.AVATAR_GRAVATAR_FIELD))).hexdigest(), urlencode(params)) return urljoin(settings.AVATAR_GRAVATAR_BASE_URL, path) + if settings.AVATAR_FACEBOOK_BACKUP: + fb_id = get_facebook_id(user) + if fb_id: + return 'https://graph.facebook.com/{fb_id}/picture?type=square&width={size}&height={size}'.format( + fb_id=fb_id, size=size + ) + return get_default_avatar_url() diff --git a/avatar/util.py b/avatar/util.py index c82c657..46717e5 100644 --- a/avatar/util.py +++ b/avatar/util.py @@ -52,7 +52,7 @@ def cache_result(default_size=settings.AVATAR_DEFAULT_SIZE): ``size`` value. """ - if settings.AVATAR_DISABLE_CACHE: + if not settings.AVATAR_CACHE_ENABLED: def decorator(func): return func return decorator diff --git a/docs/index.txt b/docs/index.txt index 96f8b5c..ac884ac 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -103,6 +103,54 @@ AVATAR_AUTO_GENERATE_SIZES upload. This can save rendering time later on if you pre-generate the resized versions. Defaults to ``(80,)`` +AVATAR_CACHE_ENABLED + Set to ``False`` if you completely disable avatar caching. Defaults to ``True``. + +AVATAR_DEFAULT_URL + The default URL to default to if ``AVATAR_GRAVATAR_BACKUP`` is set to False + and there is no ``Avatar`` instance found in the system for the given user. + +AVATAR_EXPOSE_USERNAMES + Puts the User's username field in the URL path when ``True``. Set to ``False`` to + use the User's primary key instead, preventing their email from being searchable on the web. + Defaults to ``True``. + +AVATAR_FACEBOOK_BACKUP + A bool determining whether to default to Facebook Graph service if no ``Avatar`` instance + is found in the system for the given user. ``AVATAR_GRAVATAR_BACKUP`` takes precedence, so + if you set this to ``True`` then you must set ``AVATAR_GRAVATAR_BACKUP`` to False. You + must also set the ``AVATAR_FACEBOOK_GET_ID`` setting. + Defaults to ``False``. + +AVATAR_FACEBOOK_GET_ID + A callable or string path to a callable that will return the user's Facebook ID. The + callable should take a ``User`` object and return a string. If you want to use this + then make sure ``AVATAR_FACEBOOK_BACKUP`` is ``True`` and ``AVATAR_GRAVATAR_BACKUP`` is + ``False``. Defaults to ``None``. + +AVATAR_GRAVATAR_BACKUP + A bool determining whether to default to the Gravatar service if no + ``Avatar`` instance is found in the system for the given user. Defaults to + ``True``. + +AVATAR_GRAVATAR_DEFAULT + A string determining the style of the default Gravatar. Available options + listed in the + `Gravatar documentation `_. + Ex. 'retro'. Defaults to ``None``. + +AVATAR_GRAVATAR_FIELD + The name of the user's field containing the gravatar email. For example, if you set + this to ``gravatar`` then django-avatar will get the user's gravatar in ``user.gravatar``. + Defaults to ``email``. + +AVATAR_MAX_SIZE + File size limit for avatar upload. Default is ``1024 * 1024`` (1 MB). + +AVATAR_PATH_HANDLER + Path to a method for avatar file path handling. Default is + ``avatar.models.avatar_path_handler``. + AVATAR_RESIZE_METHOD The method to use when resizing images, based on the options available in PIL. Defaults to ``Image.ANTIALIAS``. @@ -112,33 +160,6 @@ AVATAR_STORAGE_DIR non-filesystem storage device, this will simply be appended to the beginning of the file name. -AVATAR_GRAVATAR_BACKUP - A boolean determining whether to default to the Gravatar service if no - ``Avatar`` instance is found in the system for the given user. Defaults to - True. - -AVATAR_GRAVATAR_DEFAULT - A string determining the style of the default Gravatar. Available options - listed in the - `Gravatar documentation `_. - Ex. 'retro'. Defaults to None. - -AVATAR_DEFAULT_URL - The default URL to default to if ``AVATAR_GRAVATAR_BACKUP`` is set to False - and there is no ``Avatar`` instance found in the system for the given user. - -AVATAR_GRAVATAR_FIELD - The name of the user's field containing the gravatar email. For example, if you set - this to ``gravatar`` then django-avatar will get the user's gravatar in ``user.gravatar``. - Defaults to ``email``. - -AVATAR_MAX_SIZE - File size limit for avatar upload. Default is ``1024 * 1024`` (1mb). - -AVATAR_PATH_HANDLER - Path to a method for avatar file path handling. Default is - ``avatar.models.avatar_path_handler``. - Management Commands ------------------- From cd23ae11f97969617b4d91e0e00ad572cc6c914d Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Tue, 9 Feb 2016 09:13:30 -0600 Subject: [PATCH 077/119] Update changelog --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7b54037..d2308ec 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,7 @@ Changelog * 3.0 (Not released): * Added the ability to hide usernames/emails from avatar URLs. * Added the ability to use a Facebook Graph avatar as a backup. + * Added a way to customize where avatars are stored. * Added a setting to disable the avatar cache. * Fixed issue where cache was not invalidated after updating avatar * Renamed the ``avatar.util`` module to ``avatar.utils``. From 5cbd095cdabfce75440c7594d9e2080d34bd31cf Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Tue, 9 Feb 2016 09:42:29 -0600 Subject: [PATCH 078/119] Rename util -> utils, fix URL issue --- CHANGELOG.rst | 4 +++- avatar/admin.py | 2 +- avatar/models.py | 2 +- avatar/templatetags/avatar_tags.py | 4 ++-- avatar/urls.py | 2 +- avatar/{util.py => utils.py} | 1 - avatar/views.py | 4 ++-- tests/tests.py | 18 +++++++++--------- tests/urls.py | 11 ++++------- 9 files changed, 23 insertions(+), 25 deletions(-) rename avatar/{util.py => utils.py} (99%) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d2308ec..e4115ec 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,8 +6,10 @@ Changelog * Added the ability to use a Facebook Graph avatar as a backup. * Added a way to customize where avatars are stored. * Added a setting to disable the avatar cache. + * Updated thumbnail creation to preserve RGBA. + * Fixed issue where ``render_primary`` would not work if username/email was greater than 30 characters. * Fixed issue where cache was not invalidated after updating avatar - * Renamed the ``avatar.util`` module to ``avatar.utils``. + * **Backwards Incompatible:** Renamed the ``avatar.util`` module to ``avatar.utils``. * 2.2.1 (January 11, 2016) * Added AVATAR_GRAVATAR_FIELD setting to define the user field to get the gravatar email. diff --git a/avatar/admin.py b/avatar/admin.py index 8f670a9..98d833e 100644 --- a/avatar/admin.py +++ b/avatar/admin.py @@ -5,7 +5,7 @@ from django.template.loader import render_to_string from avatar.models import Avatar from avatar.signals import avatar_updated -from avatar.util import get_user_model +from avatar.utils import get_user_model class AvatarAdmin(admin.ModelAdmin): diff --git a/avatar/models.py b/avatar/models.py index c64b21b..0d4d76b 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -15,7 +15,7 @@ from django.utils import six from django.db.models import signals from avatar.conf import settings -from avatar.util import get_username, force_bytes, invalidate_cache +from avatar.utils import get_username, force_bytes, invalidate_cache try: from django.utils.timezone import now diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index 651c8d3..bf62e80 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -14,8 +14,8 @@ from django.utils.translation import ugettext as _ from django.utils.module_loading import import_string from avatar.conf import settings -from avatar.util import (get_primary_avatar, get_default_avatar_url, - cache_result, get_user_model, get_user, force_bytes) +from avatar.utils import (get_primary_avatar, get_default_avatar_url, + cache_result, get_user_model, get_user, force_bytes) from avatar.models import Avatar register = template.Library() diff --git a/avatar/urls.py b/avatar/urls.py index edb684a..b031d60 100644 --- a/avatar/urls.py +++ b/avatar/urls.py @@ -6,7 +6,7 @@ urlpatterns = [ url(r'^add/$', views.add, name='avatar_add'), url(r'^change/$', views.change, name='avatar_change'), url(r'^delete/$', views.delete, name='avatar_delete'), - url(r'^render_primary/(?P[\w\d\@\.\-_]{3,30})/(?P[\d]+)/$', + url(r'^render_primary/(?P[\w\d\@\.\-_]+)/(?P[\d]+)/$', views.render_primary, name='avatar_render_primary'), ] diff --git a/avatar/util.py b/avatar/utils.py similarity index 99% rename from avatar/util.py rename to avatar/utils.py index 46717e5..e0922f1 100644 --- a/avatar/util.py +++ b/avatar/utils.py @@ -51,7 +51,6 @@ def cache_result(default_size=settings.AVATAR_DEFAULT_SIZE): Decorator to cache the result of functions that take a ``user`` and a ``size`` value. """ - if not settings.AVATAR_CACHE_ENABLED: def decorator(func): return func diff --git a/avatar/views.py b/avatar/views.py index 18ead7c..31efe4f 100644 --- a/avatar/views.py +++ b/avatar/views.py @@ -9,8 +9,8 @@ from avatar.conf import settings from avatar.forms import PrimaryAvatarForm, DeleteAvatarForm, UploadAvatarForm from avatar.models import Avatar from avatar.signals import avatar_updated -from avatar.util import (get_primary_avatar, get_default_avatar_url, - invalidate_cache) +from avatar.utils import (get_primary_avatar, get_default_avatar_url, + invalidate_cache) def _get_next(request): diff --git a/tests/tests.py b/tests/tests.py index 07c9f46..5914a73 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -7,7 +7,7 @@ from django.test.utils import override_settings from avatar.admin import AvatarAdmin from avatar.conf import settings -from avatar.util import get_primary_avatar, get_user_model +from avatar.utils import get_primary_avatar, get_user_model from avatar.models import Avatar from PIL import Image @@ -158,14 +158,6 @@ class AvatarTests(TestCase): self.assertNotEqual(response.context['upload_avatar_form'].errors, {}) self.assertEqual(count_before, count_after) - # def testAvatarOrder - # def testReplaceAvatarWhenMaxIsOne - # def testHashFileName - # def testHashUserName - # def testChangePrimaryAvatar - # def testDeleteThumbnailAndRecreation - # def testAutomaticThumbnailCreation - @override_settings(AVATAR_THUMB_FORMAT='png') def testAutomaticThumbnailCreationRGBA(self): upload_helper(self, "django.png") @@ -178,3 +170,11 @@ class AvatarTests(TestCase): avatar = get_primary_avatar(self.user) image = Image.open(avatar.avatar.storage.open(avatar.avatar_name(settings.AVATAR_DEFAULT_SIZE), 'rb')) self.assertEqual(image.mode, 'RGB') + + # def testAvatarOrder + # def testReplaceAvatarWhenMaxIsOne + # def testHashFileName + # def testHashUserName + # def testChangePrimaryAvatar + # def testDeleteThumbnailAndRecreation + # def testAutomaticThumbnailCreation diff --git a/tests/urls.py b/tests/urls.py index 52c00f4..ae590d0 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -1,9 +1,6 @@ -try: - from django.conf.urls import patterns, include -except ImportError: - from django.conf.urls.defaults import patterns, include +from django.conf.urls import include, url -urlpatterns = patterns('', - (r'^avatar/', include('avatar.urls')), -) +urlpatterns = [ + url(r'^avatar/', include('avatar.urls')), +] From 937645372123d17e7cc110c991cf7bcdbd35f8b3 Mon Sep 17 00:00:00 2001 From: Ryan Pineo Date: Tue, 9 Feb 2016 10:49:59 -0500 Subject: [PATCH 079/119] clarify AVATAR_GRAVATAR_DEFAULT docs --- docs/index.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/index.txt b/docs/index.txt index ac884ac..88767f8 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -134,10 +134,10 @@ AVATAR_GRAVATAR_BACKUP ``True``. AVATAR_GRAVATAR_DEFAULT - A string determining the style of the default Gravatar. Available options - listed in the + A string determining the default Gravatar. Can be a URL to a custom image or a + style of Gravatar. Ex. `retro`. All Available options listed in the `Gravatar documentation `_. - Ex. 'retro'. Defaults to ``None``. + Defaults to ``None``. AVATAR_GRAVATAR_FIELD The name of the user's field containing the gravatar email. For example, if you set From d974f45cab6375533385735d1db9b1fac1a4f2e1 Mon Sep 17 00:00:00 2001 From: Orion Buske Date: Thu, 11 Feb 2016 12:51:59 -0500 Subject: [PATCH 080/119] Added GRAVITAR_FORCEDEFAULT setting --- avatar/conf.py | 1 + avatar/templatetags/avatar_tags.py | 2 ++ docs/index.txt | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/avatar/conf.py b/avatar/conf.py index 05e36af..645fa25 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -13,6 +13,7 @@ class AvatarConf(AppConf): GRAVATAR_FIELD = 'email' GRAVATAR_BACKUP = True GRAVATAR_DEFAULT = None + AVATAR_GRAVATAR_FORCEDEFAULT = False DEFAULT_URL = 'avatar/img/default.jpg' MAX_AVATARS_PER_USER = 42 MAX_SIZE = 1024 * 1024 diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index bf62e80..4dc7963 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -40,6 +40,8 @@ def avatar_url(user, size=settings.AVATAR_DEFAULT_SIZE): params = {'s': str(size)} if settings.AVATAR_GRAVATAR_DEFAULT: params['d'] = settings.AVATAR_GRAVATAR_DEFAULT + if settings.AVATAR_GRAVATAR_FORCEDEFAULT: + params['f'] = 'y' path = "%s/?%s" % (hashlib.md5(force_bytes(getattr(user, settings.AVATAR_GRAVATAR_FIELD))).hexdigest(), urlencode(params)) return urljoin(settings.AVATAR_GRAVATAR_BASE_URL, path) diff --git a/docs/index.txt b/docs/index.txt index 88767f8..1a6dd05 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -139,6 +139,11 @@ AVATAR_GRAVATAR_DEFAULT `Gravatar documentation `_. Defaults to ``None``. +AVATAR_GRAVATAR_FORCEDEFAULT + A bool indicating whether or not to always use the default Gravitar. More details can be found + in the `Gravatar documentation `_. + Defaults to ``False``. + AVATAR_GRAVATAR_FIELD The name of the user's field containing the gravatar email. For example, if you set this to ``gravatar`` then django-avatar will get the user's gravatar in ``user.gravatar``. From 09aa0c819141e13344106baa4386a2ad23fbe787 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 11 Feb 2016 15:16:38 -0600 Subject: [PATCH 081/119] Update setup.py classifiers and travis Django versions --- .travis.yml | 14 +++++++------- setup.py | 6 ++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7a04e5e..ff9d528 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,18 +13,18 @@ install: - pip install Django==${DJANGO} script: make test env: - - DJANGO=1.7.10 - - DJANGO=1.8.8 - - DJANGO=1.9.1 + - DJANGO=1.7.11 + - DJANGO=1.8.9 + - DJANGO=1.9.2 matrix: exclude: - python: 3.2 - env: DJANGO=1.9.1 + env: DJANGO=1.9.2 - python: 3.3 - env: DJANGO=1.9.1 + env: DJANGO=1.9.2 - python: 3.5 - env: DJANGO=1.7.10 + env: DJANGO=1.7.11 - python: 3.5 - env: DJANGO=1.8.8 + env: DJANGO=1.8.9 after_success: - coveralls diff --git a/setup.py b/setup.py index d6f7fe4..2203682 100644 --- a/setup.py +++ b/setup.py @@ -28,10 +28,16 @@ setup( 'Environment :: Web Environment', 'Framework :: Django', 'Intended Audience :: Developers', + 'Framework :: Django', + 'Framework :: Django :: 1.7', + 'Framework :: Django :: 1.8', + 'Framework :: Django :: 1.9', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', + 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', From 3c4cde1730460bab4dfb66cd5a4e1ed886200844 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Thu, 11 Feb 2016 15:36:19 -0600 Subject: [PATCH 082/119] Add some more tests --- tests/tests.py | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index 5914a73..9c3874c 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -9,6 +9,7 @@ from avatar.admin import AvatarAdmin from avatar.conf import settings from avatar.utils import get_primary_avatar, get_user_model from avatar.models import Avatar +from avatar.templatetags import avatar_tags from PIL import Image @@ -159,18 +160,56 @@ class AvatarTests(TestCase): self.assertEqual(count_before, count_after) @override_settings(AVATAR_THUMB_FORMAT='png') - def testAutomaticThumbnailCreationRGBA(self): + def test_automatic_thumbnail_creation_RGBA(self): upload_helper(self, "django.png") avatar = get_primary_avatar(self.user) image = Image.open(avatar.avatar.storage.open(avatar.avatar_name(settings.AVATAR_DEFAULT_SIZE), 'rb')) self.assertEqual(image.mode, 'RGBA') - def testAutomaticThumbnailCreationCMYK(self): + def test_automatic_thumbnail_creation_CMYK(self): upload_helper(self, "django_pony_cmyk.jpg") avatar = get_primary_avatar(self.user) image = Image.open(avatar.avatar.storage.open(avatar.avatar_name(settings.AVATAR_DEFAULT_SIZE), 'rb')) self.assertEqual(image.mode, 'RGB') + def test_has_avatar_False_if_no_avatar(self): + self.assertFalse(avatar_tags.has_avatar(self.user)) + + def test_has_avatar_False_if_not_user_model(self): + self.assertFalse(avatar_tags.has_avatar("Look, I'm a string")) + + def test_has_avatar_True(self): + upload_helper(self, "test.png") + + self.assertTrue(avatar_tags.has_avatar(self.user)) + + def test_avatar_tag_works_with_username(self): + upload_helper(self, "test.png") + avatar = get_primary_avatar(self.user) + + result = avatar_tags.avatar(self.user.username) + + self.assertIn('', result) + + def test_avatar_tag_works_with_user(self): + upload_helper(self, "test.png") + avatar = get_primary_avatar(self.user) + + result = avatar_tags.avatar(self.user) + + self.assertIn('', result) + + def test_avatar_tag_works_with_custom_size(self): + upload_helper(self, "test.png") + avatar = get_primary_avatar(self.user) + + result = avatar_tags.avatar(self.user, 100) + + self.assertIn('', result) + # def testAvatarOrder # def testReplaceAvatarWhenMaxIsOne # def testHashFileName From 8a8330b691aabd78cd5044a72ad52d04d3fdcb40 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Fri, 26 Feb 2016 10:45:21 -0600 Subject: [PATCH 083/119] Bump version to 3.0.0 --- CHANGELOG.rst | 2 +- avatar/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e4115ec..7c4a994 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Changelog ========= -* 3.0 (Not released): +* 3.0 (February 26, 2016): * Added the ability to hide usernames/emails from avatar URLs. * Added the ability to use a Facebook Graph avatar as a backup. * Added a way to customize where avatars are stored. diff --git a/avatar/__init__.py b/avatar/__init__.py index 36a511e..4eb28e3 100644 --- a/avatar/__init__.py +++ b/avatar/__init__.py @@ -1 +1 @@ -__version__ = '2.2.1' +__version__ = '3.0.0' From 69a9bd18b3dfae5bb52b84e6915a0f416df9ebbc Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Fri, 26 Feb 2016 10:45:45 -0600 Subject: [PATCH 084/119] Update changelog version --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7c4a994..4161e48 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Changelog ========= -* 3.0 (February 26, 2016): +* 3.0.0 (February 26, 2016): * Added the ability to hide usernames/emails from avatar URLs. * Added the ability to use a Facebook Graph avatar as a backup. * Added a way to customize where avatars are stored. From 5cb80dee99be2a50e588546fb43bf23c7ac1201a Mon Sep 17 00:00:00 2001 From: Ryan Pineo Date: Wed, 2 Mar 2016 16:14:52 -0500 Subject: [PATCH 085/119] add default of AVATAR_STORAGE_DIR to docs --- docs/index.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.txt b/docs/index.txt index 1a6dd05..3fc6fd9 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -163,7 +163,7 @@ AVATAR_RESIZE_METHOD AVATAR_STORAGE_DIR The directory under ``MEDIA_ROOT`` to store the images. If using a non-filesystem storage device, this will simply be appended to the beginning - of the file name. + of the file name. Defaults to ``avatars``. Management Commands ------------------- From 9ab18a72d89145de86ed77e03e46842f25888924 Mon Sep 17 00:00:00 2001 From: Hsinfu Huang Date: Tue, 22 Mar 2016 19:11:45 +0800 Subject: [PATCH 086/119] add feature of customizing the attribute of avatar img --- avatar/templates/avatar/avatar_tag.html | 2 +- avatar/templatetags/avatar_tags.py | 5 +++-- docs/index.txt | 9 +++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/avatar/templates/avatar/avatar_tag.html b/avatar/templates/avatar/avatar_tag.html index 79f3e61..e6a3db2 100644 --- a/avatar/templates/avatar/avatar_tag.html +++ b/avatar/templates/avatar/avatar_tag.html @@ -1 +1 @@ -{{ alt }} \ No newline at end of file +{{ alt }} \ No newline at end of file diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index 4dc7963..29cc256 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -70,12 +70,13 @@ def avatar(user, size=settings.AVATAR_DEFAULT_SIZE, **kwargs): else: alt = six.text_type(user) url = avatar_url(user, size) - context = dict(kwargs, **{ + context = { 'user': user, 'url': url, 'alt': alt, 'size': size, - }) + 'kwargs': kwargs, + } return render_to_string('avatar/avatar_tag.html', context) diff --git a/docs/index.txt b/docs/index.txt index 3fc6fd9..e96cc3a 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -68,6 +68,10 @@ that are required. A minimal integration can work like this: {% avatar user 65 %} + Example for customize the attribute of the HTML ``img`` tag:: + + {% avatar user 65 class="img-circle img-responsive" id="user_avatar" %} + Template tags and filter ------------------------ @@ -80,10 +84,11 @@ template rendering system:: Renders the URL of the avatar for the given user. User can be either a ``django.contrib.auth.models.User`` object instance or a username. -``{% avatar user [size in pixels] %}`` +``{% avatar user [size in pixels] **kwargs %}`` Renders an HTML ``img`` tag for the given user for the specified size. User can be either a ``django.contrib.auth.models.User`` object instance or a - username. + username. The (key, value) pairs in kwargs will be added to ``img`` tag + as its attributes. ``{% render_avatar avatar [size in pixels] %}`` Given an actual ``avatar.models.Avatar`` object instance, renders an HTML From 9de22c00c466a37249321746d6940e65858391a8 Mon Sep 17 00:00:00 2001 From: Ali Karbassi Date: Wed, 20 Apr 2016 18:40:22 -0500 Subject: [PATCH 087/119] Maintain verbosity settings. Fixes #20 --- avatar/management/commands/rebuild_avatars.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/avatar/management/commands/rebuild_avatars.py b/avatar/management/commands/rebuild_avatars.py index 63b3554..9be08a8 100644 --- a/avatar/management/commands/rebuild_avatars.py +++ b/avatar/management/commands/rebuild_avatars.py @@ -11,5 +11,7 @@ class Command(NoArgsCommand): def handle_noargs(self, **options): for avatar in Avatar.objects.all(): for size in settings.AVATAR_AUTO_GENERATE_SIZES: - print("Rebuilding Avatar id=%s at size %s." % (avatar.id, size)) + if options['verbosity'] != 0: + print("Rebuilding Avatar id=%s at size %s." % (avatar.id, size)) + avatar.create_thumbnail(size) From d63dbd476c45594e04303dc3a03444ba1a82382f Mon Sep 17 00:00:00 2001 From: Sergey Fedoseev Date: Thu, 26 May 2016 00:21:38 +0500 Subject: [PATCH 088/119] Fixed migrations path in .coveragerc. --- .coveragerc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.coveragerc b/.coveragerc index 67ec35c..f708e20 100644 --- a/.coveragerc +++ b/.coveragerc @@ -16,7 +16,7 @@ exclude_lines = if __name__ == .__main__.: omit = - avatar/*/migrations/* + avatar/migrations/* show_missing = True precision = 2 From 0f492e3bf43bfa3f4098be717e620afb5abaac94 Mon Sep 17 00:00:00 2001 From: Christian Sauer Date: Thu, 4 Aug 2016 17:31:04 -0400 Subject: [PATCH 089/119] Smallest/Fastest/Easiest/Least Invasive way to get custom templates --- avatar/conf.py | 3 +++ avatar/views.py | 10 ++++++---- docs/index.txt | 9 +++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/avatar/conf.py b/avatar/conf.py index 645fa25..fd8122f 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -31,6 +31,9 @@ class AvatarConf(AppConf): FACEBOOK_GET_ID = None CACHE_ENABLED = True RANDOMIZE_HASHES = False + ADD_TEMPLATE = '' + CHANGE_TEMPLATE = '' + DELETE_TEMPLATE = '' def configure_auto_generate_avatar_sizes(self, value): return value or getattr(settings, 'AVATAR_AUTO_GENERATE_SIZES', diff --git a/avatar/views.py b/avatar/views.py index 31efe4f..0e4804b 100644 --- a/avatar/views.py +++ b/avatar/views.py @@ -80,7 +80,8 @@ def add(request, extra_context=None, next_override=None, 'next': next_override or _get_next(request), } context.update(extra_context) - return render(request, 'avatar/add.html', context) + template_name = settings.AVATAR_ADD_TEMPLATE or 'avatar/add.html' + return render(request, template_name, context) @login_required @@ -120,7 +121,8 @@ def change(request, extra_context=None, next_override=None, 'next': next_override or _get_next(request) } context.update(extra_context) - return render(request, 'avatar/change.html', context) + template_name = settings.AVATAR_CHANGE_TEMPLATE or 'avatar/change.html' + return render(request, template_name, context) @login_required @@ -155,8 +157,8 @@ def delete(request, extra_context=None, next_override=None, *args, **kwargs): 'next': next_override or _get_next(request), } context.update(extra_context) - - return render(request, 'avatar/confirm_delete.html', context) + template_name = settings.AVATAR_DELETE_TEMPLATE or 'avatar/confirm_delete.html' + return render(request, template_name, context) def render_primary(request, user=None, size=settings.AVATAR_DEFAULT_SIZE): diff --git a/docs/index.txt b/docs/index.txt index e96cc3a..425fd7b 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -170,6 +170,15 @@ AVATAR_STORAGE_DIR non-filesystem storage device, this will simply be appended to the beginning of the file name. Defaults to ``avatars``. +AVATAR_ADD_TEMPLATE + Path to the Django template to use for adding a new avatar. Defaults to ``avatar/add.html``. + +AVATAR_CHANGE_TEMPLATE + Path to the Django template to use for changing a user's avatar. Defaults to ``avatar/change.html``. + +AVATAR_DELETE_TEMPLATE + Path to the Django template to use for confirming a delete of a user's avatar. Defaults to ``avatar/avatar/confirm_delete.html``. + Management Commands ------------------- From 0ea9c6a03893fb633b8be85136850e3b012f5164 Mon Sep 17 00:00:00 2001 From: Christian Sauer Date: Wed, 17 Aug 2016 11:08:45 -0400 Subject: [PATCH 090/119] tests for user templates --- tests/settings.py | 18 ++++++++++++++++++ tests/templates/alt/add.html | 1 + tests/templates/alt/change.html | 1 + tests/templates/alt/delete.html | 1 + tests/tests.py | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+) create mode 100644 tests/templates/alt/add.html create mode 100644 tests/templates/alt/change.html create mode 100644 tests/templates/alt/delete.html diff --git a/tests/settings.py b/tests/settings.py index c85df2d..471b8fe 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1,5 +1,9 @@ +import os import django +VERSION = django.VERSION +SETTINGS_DIR = os.path.dirname(__file__) + DATABASE_ENGINE = 'sqlite3' DATABASES = { @@ -25,6 +29,20 @@ MIDDLEWARE_CLASSES = ( "django.contrib.messages.middleware.MessageMiddleware", ) +if VERSION[0] == 1 and VERSION[1] < 8: + TEMPLATE_DIRS = ( + os.path.join(SETTINGS_DIR, 'templates'), + ) +else: + TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'APP_DIRS': True, + 'DIRS': [ + os.path.join(SETTINGS_DIR, 'templates') + ] + } + ] ROOT_URLCONF = 'tests.urls' diff --git a/tests/templates/alt/add.html b/tests/templates/alt/add.html new file mode 100644 index 0000000..37d4839 --- /dev/null +++ b/tests/templates/alt/add.html @@ -0,0 +1 @@ +ALTERNATE ADD TEMPLATE diff --git a/tests/templates/alt/change.html b/tests/templates/alt/change.html new file mode 100644 index 0000000..bb8650f --- /dev/null +++ b/tests/templates/alt/change.html @@ -0,0 +1 @@ +ALTERNATE CHANGE TEMPLATE diff --git a/tests/templates/alt/delete.html b/tests/templates/alt/delete.html new file mode 100644 index 0000000..10bfe9d --- /dev/null +++ b/tests/templates/alt/delete.html @@ -0,0 +1 @@ +ALTERNATE DELETE TEMPLATE diff --git a/tests/tests.py b/tests/tests.py index 9c3874c..e8c82f1 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -210,6 +210,39 @@ class AvatarTests(TestCase): self.assertIn('', result) + def test_default_add_template(self): + response = self.client.get('/avatar/add/') + self.assertContains(response, 'Upload New Image') + self.assertNotContains(response, 'ALTERNATE ADD TEMPLATE') + + @override_settings(AVATAR_ADD_TEMPLATE='alt/add.html') + def test_custom_add_template(self): + response = self.client.get('/avatar/add/') + self.assertNotContains(response, 'Upload New Image') + self.assertContains(response, 'ALTERNATE ADD TEMPLATE') + + def test_default_change_template(self): + response = self.client.get('/avatar/change/') + self.assertContains(response, 'Upload New Image') + self.assertNotContains(response, 'ALTERNATE CHANGE TEMPLATE') + + @override_settings(AVATAR_CHANGE_TEMPLATE='alt/change.html') + def test_custom_change_template(self): + response = self.client.get('/avatar/change/') + self.assertNotContains(response, 'Upload New Image') + self.assertContains(response, 'ALTERNATE CHANGE TEMPLATE') + + def test_default_delete_template(self): + response = self.client.get('/avatar/delete/') + self.assertContains(response, 'like to delete.') + self.assertNotContains(response, 'ALTERNATE DELETE TEMPLATE') + + @override_settings(AVATAR_DELETE_TEMPLATE='alt/delete.html') + def test_custom_delete_template(self): + response = self.client.get('/avatar/delete/') + self.assertNotContains(response, 'like to delete.') + self.assertContains(response, 'ALTERNATE DELETE TEMPLATE') + # def testAvatarOrder # def testReplaceAvatarWhenMaxIsOne # def testHashFileName From 39549215866421c40d0a4bfa93ad64283781b224 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 3 Sep 2016 09:48:08 -0500 Subject: [PATCH 091/119] Update Django versions on Travis --- .travis.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index ff9d528..178ea88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,17 +14,22 @@ install: script: make test env: - DJANGO=1.7.11 - - DJANGO=1.8.9 - - DJANGO=1.9.2 + - DJANGO=1.8.14 + - DJANGO=1.9.9 + - DJANGO=1.10.1 matrix: exclude: - python: 3.2 - env: DJANGO=1.9.2 + env: DJANGO=1.10.1 - python: 3.3 - env: DJANGO=1.9.2 + env: DJANGO=1.10.1 + - python: 3.2 + env: DJANGO=1.9.9 + - python: 3.3 + env: DJANGO=1.9.9 - python: 3.5 env: DJANGO=1.7.11 - python: 3.5 - env: DJANGO=1.8.9 + env: DJANGO=1.8.14 after_success: - coveralls From e8f75cb93df39b350cd89ea0f0940827d5db59b0 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 3 Sep 2016 09:49:03 -0500 Subject: [PATCH 092/119] Add official Django 1.10 support --- CHANGELOG.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4161e48..82e1cd2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,9 @@ Changelog ========= +* 3.1.0 (Not released) + * Added Django 1.10 support + * 3.0.0 (February 26, 2016): * Added the ability to hide usernames/emails from avatar URLs. * Added the ability to use a Facebook Graph avatar as a backup. From 36087355414cee063257a2a4567c219496342c6e Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 3 Sep 2016 09:50:34 -0500 Subject: [PATCH 093/119] Only show build status for master --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 7b97236..ff11f5f 100644 --- a/README.rst +++ b/README.rst @@ -9,7 +9,7 @@ django-avatar :target: http://django-avatar.readthedocs.org/en/latest/?badge=latest :alt: Documentation Status -.. image:: https://travis-ci.org/grantmcconnaughey/django-avatar.svg +.. image:: https://travis-ci.org/grantmcconnaughey/django-avatar.svg?branch=master :target: https://travis-ci.org/grantmcconnaughey/django-avatar .. image:: https://coveralls.io/repos/grantmcconnaughey/django-avatar/badge.svg?branch=master&service=github From 90081059669dc2bd78ad72ae979fc0d22e777dd2 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 3 Sep 2016 09:52:29 -0500 Subject: [PATCH 094/119] Fix spelling typo --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 82e1cd2..616e740 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -16,7 +16,7 @@ Changelog * 2.2.1 (January 11, 2016) * Added AVATAR_GRAVATAR_FIELD setting to define the user field to get the gravatar email. - * Improved Django 1.9/1.10 compability + * Improved Django 1.9/1.10 compatibility * Improved Brazilian translations * 2.2.0 (December 2, 2015) From 9ab6f0de6af935b451023c82f0790a5930d118ce Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 3 Sep 2016 09:54:58 -0500 Subject: [PATCH 095/119] Remove Python 3.2 support --- .travis.yml | 5 ----- CHANGELOG.rst | 1 + setup.py | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 178ea88..d2a1f4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: python python: - 2.7 - - 3.2 - 3.3 - 3.4 - 3.5 @@ -19,12 +18,8 @@ env: - DJANGO=1.10.1 matrix: exclude: - - python: 3.2 - env: DJANGO=1.10.1 - python: 3.3 env: DJANGO=1.10.1 - - python: 3.2 - env: DJANGO=1.9.9 - python: 3.3 env: DJANGO=1.9.9 - python: 3.5 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 616e740..5a81579 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,7 @@ Changelog * 3.1.0 (Not released) * Added Django 1.10 support + * Removed Python 3.2 support * 3.0.0 (February 26, 2016): * Added the ability to hide usernames/emails from avatar URLs. diff --git a/setup.py b/setup.py index 2203682..e31f577 100644 --- a/setup.py +++ b/setup.py @@ -32,13 +32,13 @@ setup( 'Framework :: Django :: 1.7', 'Framework :: Django :: 1.8', 'Framework :: Django :: 1.9', + 'Framework :: Django :: 1.10', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', From 9e9db99acf18a37c4197d413be35c5901539cc90 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 3 Sep 2016 09:56:43 -0500 Subject: [PATCH 096/119] Bump coverage --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index 824f13b..6112d46 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,3 +1,3 @@ flake8 -coverage==3.7.1 +coverage==4.2 django-discover-runner \ No newline at end of file From 6c5bf88fa47ad4cd4366367e0261f97745884b0a Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 3 Sep 2016 10:14:31 -0500 Subject: [PATCH 097/119] Document new features in 3.1.0 --- CHANGELOG.rst | 3 +++ README.rst | 3 +++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5a81579..6c86eec 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog ========= * 3.1.0 (Not released) + * Added the ability to override templates using ``AVATAR_ADD_TEMPLATE``, ``AVATAR_CHANGE_TEMPLATE``, and ``AVATAR_DELETE_TEMPLATE``. + * Added the ability to pass additional HTML attributes using the ``{% avatar %}`` template tag. + * Fixed unused verbosity setting in ``rebuild_avatars.py``. * Added Django 1.10 support * Removed Python 3.2 support diff --git a/README.rst b/README.rst index ff11f5f..59d927d 100644 --- a/README.rst +++ b/README.rst @@ -4,6 +4,7 @@ django-avatar .. image:: https://badge.fury.io/py/django-avatar.svg :target: https://badge.fury.io/py/django-avatar + :alt: PyPI badge .. image:: https://readthedocs.org/projects/django-avatar/badge/?version=latest :target: http://django-avatar.readthedocs.org/en/latest/?badge=latest @@ -11,9 +12,11 @@ django-avatar .. image:: https://travis-ci.org/grantmcconnaughey/django-avatar.svg?branch=master :target: https://travis-ci.org/grantmcconnaughey/django-avatar + :alt: Travis CI Build Status .. image:: https://coveralls.io/repos/grantmcconnaughey/django-avatar/badge.svg?branch=master&service=github :target: https://coveralls.io/github/grantmcconnaughey/django-avatar?branch=master + :alt: Coverage Django-avatar is a reusable application for handling user avatars. It has the ability to default to Gravatar if no avatar is found for a certain user. From 839220c51bfa17cd1683c86e6f7c6fab4528ec64 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 3 Sep 2016 10:47:01 -0500 Subject: [PATCH 098/119] Add test project for debugging --- .gitignore | 2 + test_proj/manage.py | 26 ++++++++ test_proj/test_proj/__init__.py | 0 test_proj/test_proj/settings.py | 106 ++++++++++++++++++++++++++++++++ test_proj/test_proj/urls.py | 17 +++++ test_proj/test_proj/wsgi.py | 16 +++++ 6 files changed, 167 insertions(+) create mode 100755 test_proj/manage.py create mode 100644 test_proj/test_proj/__init__.py create mode 100644 test_proj/test_proj/settings.py create mode 100644 test_proj/test_proj/urls.py create mode 100644 test_proj/test_proj/wsgi.py diff --git a/.gitignore b/.gitignore index 085aa08..f9e4d1d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ avatars .coverage docs/_build htmlcov/ +*.sqlite3 +test_proj/media diff --git a/test_proj/manage.py b/test_proj/manage.py new file mode 100755 index 0000000..d61e194 --- /dev/null +++ b/test_proj/manage.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_proj.settings") + + # Add the django-avatar directory to the Python path. That way the + # avatar module can be imported. + sys.path.append('..') + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/test_proj/test_proj/__init__.py b/test_proj/test_proj/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test_proj/test_proj/settings.py b/test_proj/test_proj/settings.py new file mode 100644 index 0000000..81638d8 --- /dev/null +++ b/test_proj/test_proj/settings.py @@ -0,0 +1,106 @@ +""" +Django settings for test_proj project. + +Generated by 'django-admin startproject' using Django 1.10.1. + +For more information on this file, see +https://docs.djangoproject.com/en/1.10/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.10/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '0o$jym8^hgw%vwx9hy%@ncr!29n7gik30(ln$pd$!3*4zu+9dv' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + + 'avatar', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'test_proj.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'test_proj.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.10/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Internationalization +# https://docs.djangoproject.com/en/1.10/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.10/howto/static-files/ + +STATIC_URL = '/static/' + +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_URL = '/media/' diff --git a/test_proj/test_proj/urls.py b/test_proj/test_proj/urls.py new file mode 100644 index 0000000..1144ca1 --- /dev/null +++ b/test_proj/test_proj/urls.py @@ -0,0 +1,17 @@ +from django.conf import settings +from django.conf.urls import url, include +from django.contrib import admin +from django.views.static import serve + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'^avatar/', include('avatar.urls')), +] + + +if settings.DEBUG: + # static files (images, css, javascript, etc.) + urlpatterns += [ + url(r'^media/(?P.*)$', serve, { + 'document_root': settings.MEDIA_ROOT}) + ] diff --git a/test_proj/test_proj/wsgi.py b/test_proj/test_proj/wsgi.py new file mode 100644 index 0000000..d02e19f --- /dev/null +++ b/test_proj/test_proj/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for test_proj project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_proj.settings") + +application = get_wsgi_application() From 0c16c0cbe2156dafa3e3b980ef0b00ef01794d16 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 10 Sep 2016 11:05:36 -0500 Subject: [PATCH 099/119] Set version 3.1.0 --- CHANGELOG.rst | 2 +- avatar/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6c86eec..f644c01 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Changelog ========= -* 3.1.0 (Not released) +* 3.1.0 (September 10, 2016) * Added the ability to override templates using ``AVATAR_ADD_TEMPLATE``, ``AVATAR_CHANGE_TEMPLATE``, and ``AVATAR_DELETE_TEMPLATE``. * Added the ability to pass additional HTML attributes using the ``{% avatar %}`` template tag. * Fixed unused verbosity setting in ``rebuild_avatars.py``. diff --git a/avatar/__init__.py b/avatar/__init__.py index 4eb28e3..7f5601d 100644 --- a/avatar/__init__.py +++ b/avatar/__init__.py @@ -1 +1 @@ -__version__ = '3.0.0' +__version__ = '3.1.0' From dc145ed57a72bae5addaecbf834dafb09c05a57f Mon Sep 17 00:00:00 2001 From: Jannis Date: Tue, 13 Sep 2016 13:29:23 +0200 Subject: [PATCH 100/119] Introduce avatar providers. --- avatar/conf.py | 7 +- avatar/providers.py | 84 +++++++++++++++++ avatar/templatetags/avatar_tags.py | 52 +++-------- docs/index.txt | 145 +++++++++++++++++++---------- 4 files changed, 195 insertions(+), 93 deletions(-) create mode 100644 avatar/providers.py diff --git a/avatar/conf.py b/avatar/conf.py index fd8122f..bfe51ef 100644 --- a/avatar/conf.py +++ b/avatar/conf.py @@ -11,7 +11,6 @@ class AvatarConf(AppConf): PATH_HANDLER = 'avatar.models.avatar_path_handler' GRAVATAR_BASE_URL = 'https://www.gravatar.com/avatar/' GRAVATAR_FIELD = 'email' - GRAVATAR_BACKUP = True GRAVATAR_DEFAULT = None AVATAR_GRAVATAR_FORCEDEFAULT = False DEFAULT_URL = 'avatar/img/default.jpg' @@ -27,13 +26,17 @@ class AvatarConf(AppConf): STORAGE = settings.DEFAULT_FILE_STORAGE CLEANUP_DELETED = False AUTO_GENERATE_SIZES = (DEFAULT_SIZE,) - FACEBOOK_BACKUP = False FACEBOOK_GET_ID = None CACHE_ENABLED = True RANDOMIZE_HASHES = False ADD_TEMPLATE = '' CHANGE_TEMPLATE = '' DELETE_TEMPLATE = '' + PROVIDERS = ( + 'avatar.providers.PrimaryAvatarProvider', + 'avatar.providers.GravatarAvatarProvider', + 'avatar.providers.DefaultAvatarProvider', + ) def configure_auto_generate_avatar_sizes(self, value): return value or getattr(settings, 'AVATAR_AUTO_GENERATE_SIZES', diff --git a/avatar/providers.py b/avatar/providers.py new file mode 100644 index 0000000..7b4c5bb --- /dev/null +++ b/avatar/providers.py @@ -0,0 +1,84 @@ +import hashlib + +try: + from urllib.parse import urljoin, urlencode +except ImportError: + from urlparse import urljoin + from urllib import urlencode + + +from avatar.conf import settings +from avatar.utils import ( + force_bytes, + get_default_avatar_url, + get_primary_avatar, +) + +from django.utils.module_loading import import_string + +# If the FacebookAvatarProvider is used, a mechanism needs to be defined on +# how to obtain the user's Facebook UID. This is done via +# ``AVATAR_FACEBOOK_GET_ID``. +get_facebook_id = None + +if 'avatar.providers.FacebookAvatarProvider' in settings.AVATAR_PROVIDERS: + if callable(settings.AVATAR_FACEBOOK_GET_ID): + get_facebook_id = settings.AVATAR_FACEBOOK_GET_ID + else: + get_facebook_id = import_string(settings.AVATAR_FACEBOOK_GET_ID) + + +class DefaultAvatarProvider(object): + """ + Returns the default url defined by ``settings.DEFAULT_AVATAR_URL``. + """ + + @classmethod + def get_avatar_url(self, user, size): + return get_default_avatar_url() + + +class PrimaryAvatarProvider(object): + """ + Returns the primary Avatar from the users avatar set. + """ + + @classmethod + def get_avatar_url(self, user, size): + avatar = get_primary_avatar(user, size) + if avatar: + return avatar.avatar_url(size) + + +class GravatarAvatarProvider(object): + """ + Returns the url for an avatar by the Gravatar service. + """ + + @classmethod + def get_avatar_url(self, user, size): + params = {'s': str(size)} + if settings.AVATAR_GRAVATAR_DEFAULT: + params['d'] = settings.AVATAR_GRAVATAR_DEFAULT + if settings.AVATAR_GRAVATAR_FORCEDEFAULT: + params['f'] = 'y' + path = "%s/?%s" % (hashlib.md5(force_bytes(getattr(user, + settings.AVATAR_GRAVATAR_FIELD))).hexdigest(), urlencode(params)) + + return urljoin(settings.AVATAR_GRAVATAR_BASE_URL, path) + + +class FacebookAvatarProvider(object): + """ + Returns the url of a Facebook profile image. + """ + + @classmethod + def get_avatar_url(self, user, size): + fb_id = get_facebook_id(user) + if fb_id: + url = 'https://graph.facebook.com/{fb_id}/picture?type=square&width={size}&height={size}' + return url.format( + fb_id=fb_id, + size=size + ) diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index 29cc256..1066b96 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -1,11 +1,3 @@ -import hashlib - -try: - from urllib.parse import urljoin, urlencode -except ImportError: - from urlparse import urljoin - from urllib import urlencode - from django import template from django.core.urlresolvers import reverse from django.template.loader import render_to_string @@ -14,46 +6,26 @@ from django.utils.translation import ugettext as _ from django.utils.module_loading import import_string from avatar.conf import settings -from avatar.utils import (get_primary_avatar, get_default_avatar_url, - cache_result, get_user_model, get_user, force_bytes) from avatar.models import Avatar +from avatar.utils import ( + cache_result, + get_default_avatar_url, + get_user_model, + get_user, +) + register = template.Library() -get_facebook_id = None - -if settings.AVATAR_FACEBOOK_BACKUP: - if callable(settings.AVATAR_FACEBOOK_GET_ID): - get_facebook_id = settings.AVATAR_FACEBOOK_GET_ID - else: - get_facebook_id = import_string(settings.AVATAR_FACEBOOK_GET_ID) - @cache_result() @register.simple_tag def avatar_url(user, size=settings.AVATAR_DEFAULT_SIZE): - avatar = get_primary_avatar(user, size=size) - if avatar: - return avatar.avatar_url(size) - - if settings.AVATAR_GRAVATAR_BACKUP: - params = {'s': str(size)} - if settings.AVATAR_GRAVATAR_DEFAULT: - params['d'] = settings.AVATAR_GRAVATAR_DEFAULT - if settings.AVATAR_GRAVATAR_FORCEDEFAULT: - params['f'] = 'y' - path = "%s/?%s" % (hashlib.md5(force_bytes(getattr(user, - settings.AVATAR_GRAVATAR_FIELD))).hexdigest(), urlencode(params)) - return urljoin(settings.AVATAR_GRAVATAR_BASE_URL, path) - - if settings.AVATAR_FACEBOOK_BACKUP: - fb_id = get_facebook_id(user) - if fb_id: - return 'https://graph.facebook.com/{fb_id}/picture?type=square&width={size}&height={size}'.format( - fb_id=fb_id, size=size - ) - - return get_default_avatar_url() + for provider_path in settings.AVATAR_PROVIDERS: + provider = import_string(provider_path) + avatar_url = provider.get_avatar_url(user, size) + if avatar_url: + return avatar_url @cache_result() diff --git a/docs/index.txt b/docs/index.txt index 425fd7b..c054913 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -2,9 +2,10 @@ django-avatar ============= Django-avatar is a reusable application for handling user avatars. It has the -ability to default to Gravatar_ if no avatar is found for a certain user. -Django-avatar automatically generates thumbnails and stores them to your default -file storage backend for retrieval later. +ability to default to avatars provided by third party services (like Gravatar_ +or Facebook) if no avatar is found for a certain user. Django-avatar +automatically generates thumbnails and stores them to your default file +storage backend for retrieval later. .. _Gravatar: http://gravatar.com @@ -103,89 +104,131 @@ Global Settings There are a number of settings available to easily customize the avatars that appear on the site. Listed below are those settings: -AVATAR_AUTO_GENERATE_SIZES +.. py:data:: AVATAR_AUTO_GENERATE_SIZES + An iterable of integers representing the sizes of avatars to generate on upload. This can save rendering time later on if you pre-generate the resized versions. Defaults to ``(80,)`` -AVATAR_CACHE_ENABLED +.. py:data:: AVATAR_CACHE_ENABLED + Set to ``False`` if you completely disable avatar caching. Defaults to ``True``. -AVATAR_DEFAULT_URL - The default URL to default to if ``AVATAR_GRAVATAR_BACKUP`` is set to False - and there is no ``Avatar`` instance found in the system for the given user. +.. py:data:: AVATAR_DEFAULT_URL -AVATAR_EXPOSE_USERNAMES - Puts the User's username field in the URL path when ``True``. Set to ``False`` to - use the User's primary key instead, preventing their email from being searchable on the web. - Defaults to ``True``. + The default URL to default to if the + :py:class:`~avatar.providers.GravatarAvatarProvider` is not used and there + is no ``Avatar`` instance found in the system for the given user. -AVATAR_FACEBOOK_BACKUP - A bool determining whether to default to Facebook Graph service if no ``Avatar`` instance - is found in the system for the given user. ``AVATAR_GRAVATAR_BACKUP`` takes precedence, so - if you set this to ``True`` then you must set ``AVATAR_GRAVATAR_BACKUP`` to False. You - must also set the ``AVATAR_FACEBOOK_GET_ID`` setting. - Defaults to ``False``. +.. py:data:: AVATAR_EXPOSE_USERNAMES -AVATAR_FACEBOOK_GET_ID - A callable or string path to a callable that will return the user's Facebook ID. The - callable should take a ``User`` object and return a string. If you want to use this - then make sure ``AVATAR_FACEBOOK_BACKUP`` is ``True`` and ``AVATAR_GRAVATAR_BACKUP`` is - ``False``. Defaults to ``None``. + Puts the User's username field in the URL path when ``True``. Set to + ``False`` to use the User's primary key instead, preventing their email + from being searchable on the web. Defaults to ``True``. -AVATAR_GRAVATAR_BACKUP - A bool determining whether to default to the Gravatar service if no - ``Avatar`` instance is found in the system for the given user. Defaults to - ``True``. +.. py:data:: AVATAR_FACEBOOK_GET_ID -AVATAR_GRAVATAR_DEFAULT - A string determining the default Gravatar. Can be a URL to a custom image or a - style of Gravatar. Ex. `retro`. All Available options listed in the - `Gravatar documentation `_. - Defaults to ``None``. + A callable or string path to a callable that will return the user's + Facebook ID. The callable should take a ``User`` object and return a + string. If you want to use this then make sure you included + :py:class:`~avatar.providers.FacebookAvatarProvider` in :py:data:`AVATAR_PROVIDERS`. -AVATAR_GRAVATAR_FORCEDEFAULT - A bool indicating whether or not to always use the default Gravitar. More details can be found - in the `Gravatar documentation `_. - Defaults to ``False``. +.. py:data:: AVATAR_GRAVATAR_DEFAULT -AVATAR_GRAVATAR_FIELD - The name of the user's field containing the gravatar email. For example, if you set - this to ``gravatar`` then django-avatar will get the user's gravatar in ``user.gravatar``. - Defaults to ``email``. + A string determining the default Gravatar. Can be a URL to a custom image + or a style of Gravatar. Ex. `retro`. All Available options listed in the + `Gravatar documentation `_. Defaults to ``None``. + +.. py:data:: AVATAR_GRAVATAR_FORCEDEFAULT + + A bool indicating whether or not to always use the default Gravitar. More + details can be found in the `Gravatar documentation + `_. Defaults + to ``False``. + +.. py:data:: AVATAR_GRAVATAR_FIELD + + The name of the user's field containing the gravatar email. For example, + if you set this to ``gravatar`` then django-avatar will get the user's + gravatar in ``user.gravatar``. Defaults to ``email``. + +.. py:data:: AVATAR_MAX_SIZE -AVATAR_MAX_SIZE File size limit for avatar upload. Default is ``1024 * 1024`` (1 MB). -AVATAR_PATH_HANDLER +.. py:data:: AVATAR_PATH_HANDLER + Path to a method for avatar file path handling. Default is ``avatar.models.avatar_path_handler``. -AVATAR_RESIZE_METHOD +.. py:data:: AVATAR_PROVIDERS + + Tuple of classes that are tried in the given order for returning avatar + URLs. + Defaults to:: + + ( + 'avatar.providers.PrimaryAvatarProvider', + 'avatar.providers.GravatarAvatarProvider', + 'avatar.providers.DefaultAvatarProvider', + ) + + If you want to implement your own provider, it must provide a class method + ``get_avatar_url(user, size)``. + + .. py:class:: avatar.providers.GravatarAvatarProvider + + Returns the primary avatar stored for the given user. + + .. py:class:: avatar.providers.GravatarAvatarProvider + + Adds support for the Gravatar service and will always return an avatar + URL. If the user has no avatar registered with Gravatar a default will + be used (see :py:data:`AVATAR_GRAVATAR_DEFAULT`). + + .. py:class:: avatar.providers.FacebookAvatarProvider + + Add this provider to :py:data:`AVATAR_PROVIDERS` in order to add + support for profile images from Facebook. Note that you also need to + set the :py:data:`AVATAR_FACEBOOK_GET_ID` setting. + + .. py:class:: avatar.providers.DefaultAvatarProvider + + Provides a fallback avatar defined in :py:data:`AVATAR_DEFAULT_URL`. + +.. py:data:: AVATAR_RESIZE_METHOD + The method to use when resizing images, based on the options available in PIL. Defaults to ``Image.ANTIALIAS``. -AVATAR_STORAGE_DIR +.. py:data:: AVATAR_STORAGE_DIR + The directory under ``MEDIA_ROOT`` to store the images. If using a non-filesystem storage device, this will simply be appended to the beginning of the file name. Defaults to ``avatars``. -AVATAR_ADD_TEMPLATE - Path to the Django template to use for adding a new avatar. Defaults to ``avatar/add.html``. +.. py:data:: AVATAR_ADD_TEMPLATE + + Path to the Django template to use for adding a new avatar. Defaults to + ``avatar/add.html``. + +.. py:data:: AVATAR_CHANGE_TEMPLATE -AVATAR_CHANGE_TEMPLATE Path to the Django template to use for changing a user's avatar. Defaults to ``avatar/change.html``. -AVATAR_DELETE_TEMPLATE - Path to the Django template to use for confirming a delete of a user's avatar. Defaults to ``avatar/avatar/confirm_delete.html``. +.. py:data:: AVATAR_DELETE_TEMPLATE + + Path to the Django template to use for confirming a delete of a user's + avatar. Defaults to ``avatar/avatar/confirm_delete.html``. Management Commands ------------------- This application does include one management command: ``rebuild_avatars``. It takes no arguments and, when run, re-renders all of the thumbnails for all of -the avatars for the pixel sizes specified in the ``AVATAR_AUTO_GENERATE_SIZES`` -setting. +the avatars for the pixel sizes specified in the +:py:data:`AVATAR_AUTO_GENERATE_SIZES` setting. .. _pip: http://www.pip-installer.org/ From a19debce22c0bd82101436e9e5f946c644da970a Mon Sep 17 00:00:00 2001 From: Jannis Date: Wed, 14 Sep 2016 13:08:12 +0200 Subject: [PATCH 101/119] Improve German translation. --- avatar/locale/de/LC_MESSAGES/django.mo | Bin 2846 -> 2998 bytes avatar/locale/de/LC_MESSAGES/django.po | 55 ++++++++++++++----------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/avatar/locale/de/LC_MESSAGES/django.mo b/avatar/locale/de/LC_MESSAGES/django.mo index 28e79ca56bea6962d5974e2306370fd353d0a721..7d50ea81ac5d02150abe5203d19010a9529973b1 100644 GIT binary patch delta 1235 zcma*lPe>F|90%~Xy6ftgS>~UFgcq^Ysd-|si`thL-$`qC8L zBv>ujXRzO4cVJr){9t{BS@;buz_BVq9QXt_z<4z_Y=KR%10IJOJO)SM5S)Tt@IE{X zU&C{Rl*ngXoWPCWa1qu<3AqjLzzO&U>X5_;xdBFCQ0yZ(4WGknDDEd*!g&1FN7p6uvI3R$mRrR(h*6Q8qB5MN}i2No~P2_rl7kqbU!%hrWD1H zaz#(46Blxx5Zsno*OWZz?#E<3VI^I~{}K7nP;dlIxa5lAm^to$s>*D&SO1Fmo3Xb3 z6g`mj$Vua|V)Kk}?(&>eC-dq}E?m>Gb?SeNrSy!d^{PEXG^6SL!(CdBrYSSi>MUP1 zgCKRBNv_i#Ei<5M!)m6FW_opPFpTpzYVMUrlqu#)bzU&rwStl86nE^R$BJB?=WO}F zS*Llf+)}S{n~UAh8HeXhNi(UT)UfjZ=}PKy)8=;CG%zc`)xS?G0$CNhUM?X2NIV}DLGx+eqmUsVb0{}q*4p> z-0tA)FV~(fO&Vgq#x+mmIpw0@SVh6joI#7++Ag~}L#D`~asPBgCQO^!+~bENHk_P+ hO-vI(7zW@e<);)8ML!~-FP(~OpFIlBzW;8#*=!&m>A<#4<7WOCSLTNw&7=z>9arI&V2KBZU3X5l`ox* z4+%yO<{`|tn1?a1`|yMD1LomRXv0JUA-mxV*bd*oPPkEj{uS=R{cqR}{eD7D!GmxJ zX5kTd1NITJLLTE{4<5XR=ivu92bD%bGJWI@^ZJvfghpTivP z+gk_`kimU$1Ios~)$jkn4(w0b0<{K0Foc3(7=x2gZg2}8gHNG6!F$*R|H1<7XeETh zMX1BiFbM~PwNxD_pWlT8@FSE7lQu$p*uNT=j1b?Uqpcw~k)6wdG^;~Kj)1B|rh&Dp zf1Nzp-s;oZPcy*!1fdc1Nf1gkWgME2{sDf?9dxMaP)~1o)s??$Fqa!dU1Tm3v|tO` z?}hx4?g?RX%b@l5wDx{=%KyvfJ!oQmj23DICFamdZ4v60xG5;BE=88TSX1aInHKgX zzThfJLz(5mF>NbKr`2;)YC@y4S~i!=q`j8rk(IC#KA}WLY2;)ya(XBn35SEz870dX zP5F%yN0(7Lr>R*bl~LjV)7G1hu`4*W)5*P1oggY5hs5%q^NTIW;irS+j~WEbqPV zfdfTN6zpLmaG diff --git a/avatar/locale/de/LC_MESSAGES/django.po b/avatar/locale/de/LC_MESSAGES/django.po index 51777c4..5f8378f 100644 --- a/avatar/locale/de/LC_MESSAGES/django.po +++ b/avatar/locale/de/LC_MESSAGES/django.po @@ -3,49 +3,50 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # -#, fuzzy msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2011-03-28 10:59+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" +"PO-Revision-Date: 2016-09-14 13:07+0200\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: de\n" +"X-Generator: Poedit 1.8.9\n" #: forms.py:34 #, python-format msgid "" -"%(ext)s is an invalid file extension. Authorized extensions are : %" -"(valid_exts_list)s" +"%(ext)s is an invalid file extension. Authorized extensions are : " +"%(valid_exts_list)s" msgstr "" -"%(ext)s ist ein ungültiges Dateiformat. Erlaubte Formate sind: %" -"(valid_exts_list)s" +"%(ext)s ist ein ungültiges Dateiformat. Erlaubte Formate sind: " +"%(valid_exts_list)s" #: forms.py:38 #, python-format msgid "" -"Your file is too big (%(size)s), the maximum allowed size is %" -"(max_valid_size)s" +"Your file is too big (%(size)s), the maximum allowed size is " +"%(max_valid_size)s" msgstr "" "Die Datei ist zu groß (%(size)s), die Maximalgröße ist %(max_valid_size)s" #: forms.py:44 #, python-format msgid "" -"You already have %(nb_avatars)d avatars, and the maximum allowed is %" -"(nb_max_avatars)d." +"You already have %(nb_avatars)d avatars, and the maximum allowed is " +"%(nb_max_avatars)d." msgstr "" -"Sie haben bereits %(nb_avatars)d Avatarbilder hochgeladen. Das maximale " +"Sie haben bereits %(nb_avatars)d Avatarbilder hochgeladen. Die maximale " "Anzahl ist %(nb_max_avatars)d." #: forms.py:56 forms.py:67 msgid "Choices" -msgstr "" +msgstr "Auswahl" #: models.py:75 #, python-format @@ -54,15 +55,15 @@ msgstr "Avatar für %s" #: views.py:73 views.py:95 msgid "Successfully uploaded a new avatar." -msgstr "Erfolgreich einen neuen Avatar hochgeladen." +msgstr "Ein neuer Avatar wurde erfolgreich hochgeladen." #: views.py:132 msgid "Successfully updated your avatar." -msgstr "Erfolgreich Ihren Avatar aktualisiert." +msgstr "Ihr Avatar wurde erfolgreich aktualisiert." #: views.py:166 msgid "Successfully deleted the requested avatars." -msgstr "Erfolgreich den Avatar gelöscht." +msgstr "Ihr Avatar wurde erfolgreich gelöscht." #: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " @@ -83,7 +84,7 @@ msgstr "Standard auswählen" #: templates/avatar/confirm_delete.html:5 msgid "Please select the avatars that you would like to delete." -msgstr "Bitte wählen Sie die Avatar aus, die Sie löschen möchten." +msgstr "Bitte wählen Sie den Avatar aus, den Sie löschen möchten." #: templates/avatar/confirm_delete.html:8 #, python-format @@ -99,14 +100,15 @@ msgid "Delete These" msgstr "Auswahl löschen" #: templates/notification/avatar_friend_updated/full.txt:1 -#, fuzzy, python-format +#, python-format msgid "" "%(avatar_creator)s has updated their avatar %(avatar)s.\n" "\n" "http://%(current_site)s%(avatar_url)s\n" msgstr "" -"%(avatar_creator)s hat den Avatar aktualisiert " -"%(avatar)s." +"%(avatar_creator)s hat seinen/ihren Avatar %(avatar)s aktualisiert.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" #: templates/notification/avatar_friend_updated/notice.html:2 #, python-format @@ -114,8 +116,8 @@ msgid "" "%(avatar_creator)s has updated their avatar %(avatar)s." msgstr "" -"%(avatar_creator)s hat den Avatar aktualisiert " -"%(avatar)s." +"%(avatar_creator)s hat ihren/seinen Avatar " +"aktualisiert %(avatar)s." #: templates/notification/avatar_updated/full.txt:1 #, python-format @@ -124,6 +126,9 @@ msgid "" "\n" "http://%(current_site)s%(avatar_url)s\n" msgstr "" +"Ihr Avatar wurde aktualisiert. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" #: templates/notification/avatar_updated/notice.html:2 #, python-format From 112141a457e475ce43038dbe5ddc963b9a3b29f8 Mon Sep 17 00:00:00 2001 From: Jannis Date: Wed, 14 Sep 2016 14:18:00 +0200 Subject: [PATCH 102/119] Add verbose_names to Avatar model. --- avatar/locale/de/LC_MESSAGES/django.mo | Bin 2998 -> 3182 bytes avatar/locale/de/LC_MESSAGES/django.po | 65 ++++++--- avatar/locale/es/LC_MESSAGES/django.po | 68 +++++---- avatar/locale/fr/LC_MESSAGES/django.po | 98 ++++++++----- avatar/locale/ja/LC_MESSAGES/django.po | 99 ++++++++----- avatar/locale/nl/LC_MESSAGES/django.po | 59 +++++--- avatar/locale/pl/LC_MESSAGES/django.po | 44 ++++-- avatar/locale/pt_BR/LC_MESSAGES/django.po | 110 ++++++++------ avatar/locale/ru/LC_MESSAGES/django.po | 134 +++++++++++++----- avatar/locale/zh_CN/LC_MESSAGES/django.po | 47 ++++-- ...0002_add_verbose_names_to_avatar_fields.py | 44 ++++++ avatar/models.py | 28 +++- 12 files changed, 549 insertions(+), 247 deletions(-) create mode 100644 avatar/migrations/0002_add_verbose_names_to_avatar_fields.py diff --git a/avatar/locale/de/LC_MESSAGES/django.mo b/avatar/locale/de/LC_MESSAGES/django.mo index 7d50ea81ac5d02150abe5203d19010a9529973b1..e0ec16299c8c55869d2e9c0e534b1d5ac7ed2e59 100644 GIT binary patch delta 741 zcmX}p&r2IY6u|Kp6E~)f*5AJmiV>kwvZ#k5fuN;=SgJv65h`}ktqJ}}x=C89U@le= z6befZy?gK~!Jc~Sskh!stABua5b^ByO;R7ser9Huw{PBj@3`tL{c8?=6{4Hb%eZ6= zGJXVj5OXym%b3CiJjE=AgCZ7w#4zq+Gwx#pe#0o9;8Q%qVZ6eA><)+uc z_!{5iBL2eXI8ZAxju}khF}C3?&SI1*w2(JEw2+mm>-dm$9!Vu7oZ(P=xX$`FAJ6lD zNz{q#u<-?XC(%eHQ46-P?!iYGM=dmo37o?rJi^C#hH<>WR&0DA@(u^l#Y237*Eo$y zs!Q>IIbhO`f6#n@T1b-q>4~PQzC>;9E2LI&QE!QSrqy6NqwnaliLR=85Ypa<=GRE+ zy>q1|DBPU11Dh&aQjc`noLo<(cdSKd!T&>x)D~-Wmj4FqK)E$|UNhu;a0-qm74nkv zGMkR~Ns76Rth4H__BjP9=3URfu6^b&S&`7#_~@8FX~iNs8Ma4k+rP1FKWBX|$HGg2 o@M(x1nkq_ZpOHFtx&TYb)^OuAde!nW(l9hPxgjQ{`u delta 562 zcmX}pJxjw-6vpwBwl=9+tJSK5g@}q^Exm0KYZZ!ugQ$p#6bG@31yLyISfqYTK5;T!X4`9#*SfV233 zS(GM`Wtc=A_6(Qs8s`c3g*&Wsq*=vVEaMOAKxOMM=qYxxKF1K>mm5xWfErHW3l5_% zATolZn7}-C;RzP;3b)YP%S$c$Pq@FJu@rLYVY!>Ks*4_Fn0B$WXAkXH54>+4=g>bBOvY6@ sp32xsl^vUK>i)q%I;+NGDy5W@FpnL>OjPg94a2gFPmk`S;XvH`3sE{bO#lD@ diff --git a/avatar/locale/de/LC_MESSAGES/django.po b/avatar/locale/de/LC_MESSAGES/django.po index 5f8378f..ec81c4f 100644 --- a/avatar/locale/de/LC_MESSAGES/django.po +++ b/avatar/locale/de/LC_MESSAGES/django.po @@ -7,18 +7,26 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-03-28 10:59+0200\n" -"PO-Revision-Date: 2016-09-14 13:07+0200\n" +"POT-Creation-Date: 2016-09-14 16:37+0200\n" +"PO-Revision-Date: 2016-09-14 14:34+0200\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Last-Translator: \n" -"Language-Team: \n" -"Language: de\n" "X-Generator: Poedit 1.8.9\n" -#: forms.py:34 +#: admin.py:26 +msgid "Avatar" +msgstr "Avatar" + +#: forms.py:24 models.py:84 models.py:97 +msgid "avatar" +msgstr "avatar" + +#: forms.py:37 #, python-format msgid "" "%(ext)s is an invalid file extension. Authorized extensions are : " @@ -27,7 +35,7 @@ msgstr "" "%(ext)s ist ein ungültiges Dateiformat. Erlaubte Formate sind: " "%(valid_exts_list)s" -#: forms.py:38 +#: forms.py:44 #, python-format msgid "" "Your file is too big (%(size)s), the maximum allowed size is " @@ -35,7 +43,7 @@ msgid "" msgstr "" "Die Datei ist zu groß (%(size)s), die Maximalgröße ist %(max_valid_size)s" -#: forms.py:44 +#: forms.py:54 #, python-format msgid "" "You already have %(nb_avatars)d avatars, and the maximum allowed is " @@ -44,26 +52,25 @@ msgstr "" "Sie haben bereits %(nb_avatars)d Avatarbilder hochgeladen. Die maximale " "Anzahl ist %(nb_max_avatars)d." -#: forms.py:56 forms.py:67 +#: forms.py:71 forms.py:84 msgid "Choices" msgstr "Auswahl" -#: models.py:75 -#, python-format -msgid "Avatar for %s" -msgstr "Avatar für %s" +#: models.py:77 +msgid "user" +msgstr "Benutzer" -#: views.py:73 views.py:95 -msgid "Successfully uploaded a new avatar." -msgstr "Ein neuer Avatar wurde erfolgreich hochgeladen." +#: models.py:80 +msgid "primary" +msgstr "primär" -#: views.py:132 -msgid "Successfully updated your avatar." -msgstr "Ihr Avatar wurde erfolgreich aktualisiert." +#: models.py:91 +msgid "uploaded at" +msgstr "hochgeladen am" -#: views.py:166 -msgid "Successfully deleted the requested avatars." -msgstr "Ihr Avatar wurde erfolgreich gelöscht." +#: models.py:98 +msgid "avatars" +msgstr "Avatare" #: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " @@ -137,10 +144,22 @@ msgstr "" "Sie haben Ihren Avatar aktualisiert %(avatar)s." -#: templatetags/avatar_tags.py:45 +#: templatetags/avatar_tags.py:69 msgid "Default Avatar" msgstr "Standard-Avatar" +#: views.py:73 +msgid "Successfully uploaded a new avatar." +msgstr "Ein neuer Avatar wurde erfolgreich hochgeladen." + +#: views.py:111 +msgid "Successfully updated your avatar." +msgstr "Ihr Avatar wurde erfolgreich aktualisiert." + +#: views.py:150 +msgid "Successfully deleted the requested avatars." +msgstr "Ihr Avatar wurde erfolgreich gelöscht." + #~ msgid "Avatar Updated" #~ msgstr "Avatar aktualisiert" diff --git a/avatar/locale/es/LC_MESSAGES/django.po b/avatar/locale/es/LC_MESSAGES/django.po index b88a4ce..3b3cff4 100644 --- a/avatar/locale/es/LC_MESSAGES/django.po +++ b/avatar/locale/es/LC_MESSAGES/django.po @@ -7,26 +7,26 @@ msgid "" msgstr "" "Project-Id-Version: 2.0a10\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-08-26 23:53-0500\n" +"POT-Creation-Date: 2016-09-14 16:37+0200\n" "PO-Revision-Date: 2013-08-27 00:21-0600\n" "Last-Translator: David Loaiza M. \n" "Language-Team: es \n" +"Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.5.7\n" -"Language: es\n" -#: admin.py:19 +#: admin.py:26 msgid "Avatar" msgstr "Avatar" -#: forms.py:23 +#: forms.py:24 models.py:84 models.py:97 msgid "avatar" msgstr "avatar" -#: forms.py:35 +#: forms.py:37 #, python-format msgid "" "%(ext)s is an invalid file extension. Authorized extensions are : " @@ -35,7 +35,7 @@ msgstr "" "%(ext)s es una extensión de archivo inválida. Las extensiones de archivo " "autorizadas son: %(valid_exts_list)s" -#: forms.py:39 +#: forms.py:44 #, python-format msgid "" "Your file is too big (%(size)s), the maximum allowed size is " @@ -44,7 +44,7 @@ msgstr "" "Su archivo es muy grande (%(size)s), el tamaño máximo permitido es " "%(max_valid_size)s" -#: forms.py:49 +#: forms.py:54 #, python-format msgid "" "You already have %(nb_avatars)d avatars, and the maximum allowed is " @@ -53,43 +53,49 @@ msgstr "" "Usted ya tiene %(nb_avatars)d avatares, y el máximo permitido es " "%(nb_max_avatars)d." -#: forms.py:65 forms.py:77 +#: forms.py:71 forms.py:84 msgid "Choices" msgstr "Opciones" -#: views.py:71 -msgid "Successfully uploaded a new avatar." -msgstr "Se ha subido correctamente un nuevo avatar" +#: models.py:77 +msgid "user" +msgstr "" -#: views.py:106 -msgid "Successfully updated your avatar." -msgstr "Se ha actualizado correctamente su avatar." +#: models.py:80 +msgid "primary" +msgstr "" -#: views.py:141 -msgid "Successfully deleted the requested avatars." -msgstr "Se han eliminado correctamente los avatares solicitados." +#: models.py:91 +msgid "uploaded at" +msgstr "" -#: templates/avatar/add.html:6 templates/avatar/change.html:6 +#: models.py:98 +#, fuzzy +#| msgid "avatar" +msgid "avatars" +msgstr "avatar" + +#: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " msgstr "Su avatar actual:" -#: templates/avatar/add.html:9 templates/avatar/change.html:9 +#: templates/avatar/add.html:8 templates/avatar/change.html:8 msgid "You haven't uploaded an avatar yet. Please upload one now." msgstr "No ha subido un avatar aún. Por favor, suba uno ahora." -#: templates/avatar/add.html:13 templates/avatar/change.html:20 +#: templates/avatar/add.html:12 templates/avatar/change.html:19 msgid "Upload New Image" msgstr "Subir Nueva Imagen" -#: templates/avatar/change.html:15 +#: templates/avatar/change.html:14 msgid "Choose new Default" msgstr "Elige nuevo predeterminado" -#: templates/avatar/confirm_delete.html:6 +#: templates/avatar/confirm_delete.html:5 msgid "Please select the avatars that you would like to delete." msgstr "Por favor seleccione los avatares que le gustaría eliminar." -#: templates/avatar/confirm_delete.html:9 +#: templates/avatar/confirm_delete.html:8 #, python-format msgid "" "You have no avatars to delete. Please suba uno ahora." -#: templates/avatar/confirm_delete.html:15 +#: templates/avatar/confirm_delete.html:14 msgid "Delete These" msgstr "Eliminar Estos" @@ -138,6 +144,18 @@ msgstr "" msgid "You have updated your avatar %(avatar)s." msgstr "Ha actualizado su avatar %(avatar)s." -#: templatetags/avatar_tags.py:57 +#: templatetags/avatar_tags.py:69 msgid "Default Avatar" msgstr "Avatar Predeterminado" + +#: views.py:73 +msgid "Successfully uploaded a new avatar." +msgstr "Se ha subido correctamente un nuevo avatar" + +#: views.py:111 +msgid "Successfully updated your avatar." +msgstr "Se ha actualizado correctamente su avatar." + +#: views.py:150 +msgid "Successfully deleted the requested avatars." +msgstr "Se han eliminado correctamente los avatares solicitados." diff --git a/avatar/locale/fr/LC_MESSAGES/django.po b/avatar/locale/fr/LC_MESSAGES/django.po index 5312106..1b1f395 100644 --- a/avatar/locale/fr/LC_MESSAGES/django.po +++ b/avatar/locale/fr/LC_MESSAGES/django.po @@ -7,62 +7,76 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-03-28 10:59+0200\n" +"POT-Creation-Date: 2016-09-14 16:37+0200\n" "PO-Revision-Date: 2010-03-26 18:35+0100\n" "Last-Translator: Mathieu Pillard \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: forms.py:34 +#: admin.py:26 +#, fuzzy +#| msgid "Avatar for %s" +msgid "Avatar" +msgstr "Avatar pour %s" + +#: forms.py:24 models.py:84 models.py:97 +#, fuzzy +#| msgid "Default Avatar" +msgid "avatar" +msgstr "Avatar par défaut" + +#: forms.py:37 #, python-format msgid "" -"%(ext)s is an invalid file extension. Authorized extensions are : %" -"(valid_exts_list)s" +"%(ext)s is an invalid file extension. Authorized extensions are : " +"%(valid_exts_list)s" msgstr "" "%(ext)s n'est pas une extension de fichier valide. Les extensions autorisées " "sont: %(valid_exts_list)s" -#: forms.py:38 -#, python-format -msgid "" -"Your file is too big (%(size)s), the maximum allowed size is %" -"(max_valid_size)s" -msgstr "" -"Le fichier est trop gros (%(size)s), la taille maximum autorisée est %" -"(max_valid_size)s" - #: forms.py:44 #, python-format msgid "" -"You already have %(nb_avatars)d avatars, and the maximum allowed is %" -"(nb_max_avatars)d." +"Your file is too big (%(size)s), the maximum allowed size is " +"%(max_valid_size)s" msgstr "" -"Vous avez déjà %(nb_avatars)d avatars, et le maximum autorisé est %" -"(nb_max_avatars)d." +"Le fichier est trop gros (%(size)s), la taille maximum autorisée est " +"%(max_valid_size)s" -#: forms.py:56 forms.py:67 +#: forms.py:54 +#, python-format +msgid "" +"You already have %(nb_avatars)d avatars, and the maximum allowed is " +"%(nb_max_avatars)d." +msgstr "" +"Vous avez déjà %(nb_avatars)d avatars, et le maximum autorisé est " +"%(nb_max_avatars)d." + +#: forms.py:71 forms.py:84 msgid "Choices" msgstr "Choix" -#: models.py:75 -#, python-format -msgid "Avatar for %s" +#: models.py:77 +msgid "user" +msgstr "" + +#: models.py:80 +msgid "primary" +msgstr "" + +#: models.py:91 +msgid "uploaded at" +msgstr "" + +#: models.py:98 +#, fuzzy +#| msgid "Avatar for %s" +msgid "avatars" msgstr "Avatar pour %s" -#: views.py:73 views.py:95 -msgid "Successfully uploaded a new avatar." -msgstr "Votre nouveau avatar a été uploadé avec succès." - -#: views.py:132 -msgid "Successfully updated your avatar." -msgstr "Votre avatar a été mis à jour avec succès." - -#: views.py:166 -msgid "Successfully deleted the requested avatars." -msgstr "Les avatars sélectionnés ont été effacés avec succès." - #: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " msgstr "Votre avatar actuel:" @@ -89,8 +103,8 @@ msgid "" "You have no avatars to delete. Please upload one now." msgstr "" -"Vous n'avez aucun avatar à effacer. Veuillez en ajouter un maintenant." +"Vous n'avez aucun avatar à effacer. Veuillez en ajouter un maintenant." #: templates/avatar/confirm_delete.html:14 msgid "Delete These" @@ -131,10 +145,22 @@ msgstr "" msgid "You have updated your avatar %(avatar)s." msgstr "Vous avez mis à jour votre %(avatar)s." -#: templatetags/avatar_tags.py:45 +#: templatetags/avatar_tags.py:69 msgid "Default Avatar" msgstr "Avatar par défaut" +#: views.py:73 +msgid "Successfully uploaded a new avatar." +msgstr "Votre nouveau avatar a été uploadé avec succès." + +#: views.py:111 +msgid "Successfully updated your avatar." +msgstr "Votre avatar a été mis à jour avec succès." + +#: views.py:150 +msgid "Successfully deleted the requested avatars." +msgstr "Les avatars sélectionnés ont été effacés avec succès." + #~ msgid "Avatar Updated" #~ msgstr "Avatar mis à jour" diff --git a/avatar/locale/ja/LC_MESSAGES/django.po b/avatar/locale/ja/LC_MESSAGES/django.po index c417e51..c7ed798 100644 --- a/avatar/locale/ja/LC_MESSAGES/django.po +++ b/avatar/locale/ja/LC_MESSAGES/django.po @@ -8,88 +8,102 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-09-18 19:49+0900\n" +"POT-Creation-Date: 2016-09-14 16:37+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: admin.py:19 +#: admin.py:26 msgid "Avatar" msgstr "プロフィール画像" -#: forms.py:24 +#: forms.py:24 models.py:84 models.py:97 msgid "avatar" msgstr "プロフィール画像" #: forms.py:37 #, python-format msgid "" -"%(ext)s is an invalid file extension. Authorized extensions are : %" -"(valid_exts_list)s" -msgstr "%(ext)s は利用できない拡張子です。 使用可能な拡張子 : %(valid_exts_list)s" +"%(ext)s is an invalid file extension. Authorized extensions are : " +"%(valid_exts_list)s" +msgstr "" +"%(ext)s は利用できない拡張子です。 使用可能な拡張子 : %(valid_exts_list)s" #: forms.py:44 #, python-format msgid "" -"Your file is too big (%(size)s), the maximum allowed size is %" -"(max_valid_size)s" -msgstr "ファイルが大きすぎます(%(size)s)。アップロード可能な最大サイズは %(max_valid_size)s です。" +"Your file is too big (%(size)s), the maximum allowed size is " +"%(max_valid_size)s" +msgstr "" +"ファイルが大きすぎます(%(size)s)。アップロード可能な最大サイズは " +"%(max_valid_size)s です。" #: forms.py:54 #, python-format msgid "" -"You already have %(nb_avatars)d avatars, and the maximum allowed is %" -"(nb_max_avatars)d." -msgstr "登録可能なプロフィール画像は %(nb_max_avatars)d 個までです。すでに %(nb_avatars)d 個登録されています。" +"You already have %(nb_avatars)d avatars, and the maximum allowed is " +"%(nb_max_avatars)d." +msgstr "" +"登録可能なプロフィール画像は %(nb_max_avatars)d 個までです。すでに " +"%(nb_avatars)d 個登録されています。" #: forms.py:71 forms.py:84 msgid "Choices" msgstr "選択" -#: views.py:74 -msgid "Successfully uploaded a new avatar." -msgstr "新しいプロフィール画像をアップロードしました。" +#: models.py:77 +msgid "user" +msgstr "" -#: views.py:110 -msgid "Successfully updated your avatar." -msgstr "プロフィール画像を更新しました。" +#: models.py:80 +msgid "primary" +msgstr "" -#: views.py:148 -msgid "Successfully deleted the requested avatars." -msgstr "指定されたプロフィール画像を削除しました。" +#: models.py:91 +msgid "uploaded at" +msgstr "" -#: templates/avatar/add.html:6 templates/avatar/change.html:6 +#: models.py:98 +#, fuzzy +#| msgid "avatar" +msgid "avatars" +msgstr "プロフィール画像" + +#: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " msgstr "現在のプロフィール画像:" -#: templates/avatar/add.html:9 templates/avatar/change.html:9 +#: templates/avatar/add.html:8 templates/avatar/change.html:8 msgid "You haven't uploaded an avatar yet. Please upload one now." msgstr "登録されているプロフィール画像はありません。アップロードしてください。" -#: templates/avatar/add.html:13 templates/avatar/change.html:20 +#: templates/avatar/add.html:12 templates/avatar/change.html:19 msgid "Upload New Image" msgstr "新しい画像のアップロード" -#: templates/avatar/change.html:15 +#: templates/avatar/change.html:14 msgid "Choose new Default" msgstr "デフォルトの画像を選択" -#: templates/avatar/confirm_delete.html:6 +#: templates/avatar/confirm_delete.html:5 msgid "Please select the avatars that you would like to delete." msgstr "削除したいプロフィール画像を選択してください。" -#: templates/avatar/confirm_delete.html:9 +#: templates/avatar/confirm_delete.html:8 #, python-format msgid "" "You have no avatars to delete. Please upload one now." -msgstr "削除できるプロフィール画像はありません。新規画像のアップロード." +msgstr "" +"削除できるプロフィール画像はありません。新" +"規画像のアップロード." -#: templates/avatar/confirm_delete.html:15 +#: templates/avatar/confirm_delete.html:14 msgid "Delete These" msgstr "削除" @@ -99,7 +113,9 @@ msgid "" "%(avatar_creator)s has updated their avatar %(avatar)s.\n" "\n" "http://%(current_site)s%(avatar_url)s\n" -msgstr "%(avatar_creator)s さんがプロフィール画像 %(avatar)s をアップロードしました。\n" +msgstr "" +"%(avatar_creator)s さんがプロフィール画像 %(avatar)s をアップロードしまし" +"た。\n" "\n" "http://%(current_site)s%(avatar_url)s\n" @@ -108,7 +124,8 @@ msgstr "%(avatar_creator)s さんがプロフィール画像 %(avatar)s をア msgid "" "%(avatar_creator)s has updated their avatar %(avatar)s." -msgstr "%(avatar_creator)s さんがプロフィール画像 %(avatar_creator)s さんがプロフィール画像 %(avatar)s をアップロードしました。" #: templates/notification/avatar_updated/full.txt:1 @@ -117,15 +134,29 @@ msgid "" "Your avatar has been updated. %(avatar)s\n" "\n" "http://%(current_site)s%(avatar_url)s\n" -msgstr "プロフィール画像を更新しました。 %(avatar)s\n" +msgstr "" +"プロフィール画像を更新しました。 %(avatar)s\n" "\n" "http://%(current_site)s%(avatar_url)s\n" #: templates/notification/avatar_updated/notice.html:2 #, python-format msgid "You have updated your avatar %(avatar)s." -msgstr "プロフィール画像を更新しました。 %(avatar)s." +msgstr "" +"プロフィール画像を更新しました。 %(avatar)s." -#: templatetags/avatar_tags.py:51 +#: templatetags/avatar_tags.py:69 msgid "Default Avatar" msgstr "デフォルトのプロフィール画像" + +#: views.py:73 +msgid "Successfully uploaded a new avatar." +msgstr "新しいプロフィール画像をアップロードしました。" + +#: views.py:111 +msgid "Successfully updated your avatar." +msgstr "プロフィール画像を更新しました。" + +#: views.py:150 +msgid "Successfully deleted the requested avatars." +msgstr "指定されたプロフィール画像を削除しました。" diff --git a/avatar/locale/nl/LC_MESSAGES/django.po b/avatar/locale/nl/LC_MESSAGES/django.po index f35cf5d..d365526 100644 --- a/avatar/locale/nl/LC_MESSAGES/django.po +++ b/avatar/locale/nl/LC_MESSAGES/django.po @@ -7,21 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-11-11 12:32+0100\n" +"POT-Creation-Date: 2016-09-14 16:37+0200\n" "PO-Revision-Date: 2013-11-11 12:49+0100\n" "Last-Translator: Ivor \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.5.5\n" -#: admin.py:19 +#: admin.py:26 msgid "Avatar" msgstr "Profielfoto" -#: forms.py:24 +#: forms.py:24 models.py:84 models.py:97 msgid "avatar" msgstr "profielfoto" @@ -55,39 +56,45 @@ msgstr "" msgid "Choices" msgstr "Keuzes" -#: views.py:74 -msgid "Successfully uploaded a new avatar." -msgstr "De profielfoto is ververst." +#: models.py:77 +msgid "user" +msgstr "" -#: views.py:110 -msgid "Successfully updated your avatar." -msgstr "Profielfoto vernieuwd." +#: models.py:80 +msgid "primary" +msgstr "" -#: views.py:148 -msgid "Successfully deleted the requested avatars." -msgstr "Profielfoto verwijderd." +#: models.py:91 +msgid "uploaded at" +msgstr "" -#: templates/avatar/add.html:6 templates/avatar/change.html:6 +#: models.py:98 +#, fuzzy +#| msgid "avatar" +msgid "avatars" +msgstr "profielfoto" + +#: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " msgstr "De huidige profielfoto:" -#: templates/avatar/add.html:9 templates/avatar/change.html:9 +#: templates/avatar/add.html:8 templates/avatar/change.html:8 msgid "You haven't uploaded an avatar yet. Please upload one now." msgstr "Er is nog geen profielfoto. Upload een nieuwe." -#: templates/avatar/add.html:13 templates/avatar/change.html:20 +#: templates/avatar/add.html:12 templates/avatar/change.html:19 msgid "Upload New Image" msgstr "Upload nieuw plaatje" -#: templates/avatar/change.html:15 +#: templates/avatar/change.html:14 msgid "Choose new Default" msgstr "Kies nieuwe standaard" -#: templates/avatar/confirm_delete.html:6 +#: templates/avatar/confirm_delete.html:5 msgid "Please select the avatars that you would like to delete." msgstr "Selecteer de te verwijderen de profielfoto's." -#: templates/avatar/confirm_delete.html:9 +#: templates/avatar/confirm_delete.html:8 #, python-format msgid "" "You have no avatars to delete. Please Upload een nieuwe." -#: templates/avatar/confirm_delete.html:15 +#: templates/avatar/confirm_delete.html:14 msgid "Delete These" msgstr "Verwijder deze" @@ -136,6 +143,18 @@ msgstr "" msgid "You have updated your avatar %(avatar)s." msgstr "De profielfoto is vernieuwd %(avatar)s." -#: templatetags/avatar_tags.py:51 +#: templatetags/avatar_tags.py:69 msgid "Default Avatar" msgstr "Standaard profielfoto" + +#: views.py:73 +msgid "Successfully uploaded a new avatar." +msgstr "De profielfoto is ververst." + +#: views.py:111 +msgid "Successfully updated your avatar." +msgstr "Profielfoto vernieuwd." + +#: views.py:150 +msgid "Successfully deleted the requested avatars." +msgstr "Profielfoto verwijderd." diff --git a/avatar/locale/pl/LC_MESSAGES/django.po b/avatar/locale/pl/LC_MESSAGES/django.po index 110d499..b099f0c 100644 --- a/avatar/locale/pl/LC_MESSAGES/django.po +++ b/avatar/locale/pl/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: django-avatar 0.0.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-07-19 15:45+0200\n" +"POT-Creation-Date: 2016-09-14 16:37+0200\n" "PO-Revision-Date: 2015-07-19 15:46+0100\n" "Last-Translator: Adam Dobrawy \n" "Language-Team: Adam Dobrawy \n" @@ -23,7 +23,7 @@ msgstr "" msgid "Avatar" msgstr "Avatar" -#: forms.py:24 +#: forms.py:24 models.py:84 models.py:97 msgid "avatar" msgstr "avatar" @@ -58,27 +58,45 @@ msgstr "" msgid "Choices" msgstr "Opcje wyboru" -#: templates/avatar/add.html:6 templates/avatar/change.html:6 +#: models.py:77 +msgid "user" +msgstr "" + +#: models.py:80 +msgid "primary" +msgstr "" + +#: models.py:91 +msgid "uploaded at" +msgstr "" + +#: models.py:98 +#, fuzzy +#| msgid "avatar" +msgid "avatars" +msgstr "avatar" + +#: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " msgstr "Twój aktualny avatar" -#: templates/avatar/add.html:9 templates/avatar/change.html:9 +#: templates/avatar/add.html:8 templates/avatar/change.html:8 msgid "You haven't uploaded an avatar yet. Please upload one now." msgstr "Nie masz aktualnie żadnych avatarów. Prosimy wyślij teraz. " -#: templates/avatar/add.html:13 templates/avatar/change.html:20 +#: templates/avatar/add.html:12 templates/avatar/change.html:19 msgid "Upload New Image" msgstr "Wyślij nowy obraz" -#: templates/avatar/change.html:15 +#: templates/avatar/change.html:14 msgid "Choose new Default" msgstr "Wybierz nowy domyślny" -#: templates/avatar/confirm_delete.html:6 +#: templates/avatar/confirm_delete.html:5 msgid "Please select the avatars that you would like to delete." msgstr "Wybierz avatar, który chcesz usunąć." -#: templates/avatar/confirm_delete.html:9 +#: templates/avatar/confirm_delete.html:8 #, python-format msgid "" "You have no avatars to delete. Please dodaj nowy." -#: templates/avatar/confirm_delete.html:15 +#: templates/avatar/confirm_delete.html:14 msgid "Delete These" msgstr "Usuń wybrane" @@ -129,18 +147,18 @@ msgstr "" "Zaktualizowałeś / zaktualizowałaś swój avatar " "%(avatar)s." -#: templatetags/avatar_tags.py:51 +#: templatetags/avatar_tags.py:69 msgid "Default Avatar" msgstr "Domyślny avatar" -#: views.py:74 +#: views.py:73 msgid "Successfully uploaded a new avatar." msgstr "Pomyślnie wysłano nowy avatar." -#: views.py:110 +#: views.py:111 msgid "Successfully updated your avatar." msgstr "Pomyślnie zaktualizowano Twój avatar." -#: views.py:148 +#: views.py:150 msgid "Successfully deleted the requested avatars." msgstr "Pomyślnie usunięto wskazany avatar." diff --git a/avatar/locale/pt_BR/LC_MESSAGES/django.po b/avatar/locale/pt_BR/LC_MESSAGES/django.po index aad3f83..5ab487a 100644 --- a/avatar/locale/pt_BR/LC_MESSAGES/django.po +++ b/avatar/locale/pt_BR/LC_MESSAGES/django.po @@ -8,57 +8,74 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-03-28 10:59+0200\n" +"POT-Creation-Date: 2016-09-14 16:37+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: forms.py:34 +#: admin.py:26 +#, fuzzy +#| msgid "Avatar for %s" +msgid "Avatar" +msgstr "Avatar para %s" + +#: forms.py:24 models.py:84 models.py:97 +#, fuzzy +#| msgid "Default Avatar" +msgid "avatar" +msgstr "Foto de Perfil Padrão" + +#: forms.py:37 #, python-format msgid "" -"%(ext)s is an invalid file extension. Authorized extensions are : %" -"(valid_exts_list)s" -msgstr "%(ext)s é uma extensão informada inválida. Os Formatos permitidos são : %" -"(valid_exts_list)s" -#: forms.py:38 -#, python-format -msgid "" -"Your file is too big (%(size)s), the maximum allowed size is %" -"(max_valid_size)s" -msgstr "Arquivo muito grande (%(size)s), o máximo permitido é %" -"(max_valid_size)s" +"%(ext)s is an invalid file extension. Authorized extensions are : " +"%(valid_exts_list)s" +msgstr "" +"%(ext)s é uma extensão informada inválida. Os Formatos permitidos são : " +"%(valid_exts_list)s" #: forms.py:44 #, python-format msgid "" -"You already have %(nb_avatars)d avatars, and the maximum allowed is %" -"(nb_max_avatars)d." -msgstr "Você já possui %(nb_avatars)d fotos. O máximo permitido é %" -"(nb_max_avatars)d." -#: forms.py:56 forms.py:67 +"Your file is too big (%(size)s), the maximum allowed size is " +"%(max_valid_size)s" +msgstr "" +"Arquivo muito grande (%(size)s), o máximo permitido é %(max_valid_size)s" + +#: forms.py:54 +#, python-format +msgid "" +"You already have %(nb_avatars)d avatars, and the maximum allowed is " +"%(nb_max_avatars)d." +msgstr "" +"Você já possui %(nb_avatars)d fotos. O máximo permitido é %(nb_max_avatars)d." + +#: forms.py:71 forms.py:84 msgid "Choices" msgstr "Opções" -#: models.py:75 -#, python-format -msgid "Avatar for %s" +#: models.py:77 +msgid "user" +msgstr "" + +#: models.py:80 +msgid "primary" +msgstr "" + +#: models.py:91 +msgid "uploaded at" +msgstr "" + +#: models.py:98 +#, fuzzy +#| msgid "Avatar for %s" +msgid "avatars" msgstr "Avatar para %s" -#: views.py:73 views.py:95 -msgid "Successfully uploaded a new avatar." -msgstr "Nova foto de perfil enviada com sucesso." - -#: views.py:132 -msgid "Successfully updated your avatar." -msgstr "Sua foto foi atualizada com sucesso." - -#: views.py:166 -msgid "Successfully deleted the requested avatars." -msgstr "As fotos de perfil selecionadas foram excluídas com sucesso." - #: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " msgstr "Sua foto atual:" @@ -84,8 +101,9 @@ msgstr "Por favor, selecione as fotos que você deseja excluir" msgid "" "You have no avatars to delete. Please upload one now." -msgstr "Você não possui uma foto. Deseja enviar uma agora?" +msgstr "" +"Você não possui uma foto. Deseja enviar " +"uma agora?" #: templates/avatar/confirm_delete.html:14 msgid "Delete These" @@ -97,9 +115,9 @@ msgid "" "%(avatar_creator)s has updated their avatar %(avatar)s.\n" "\n" "http://%(current_site)s%(avatar_url)s\n" -msgstr "%(avatar_creator)s atualizou a foto do perfil %(avatar)s.\n" +msgstr "" +"%(avatar_creator)s atualizou a foto do perfil %(avatar)s.\n" "\n" - "%(avatar_creator)s atualizou a foto de perfil " "%(avatar)s." @@ -118,11 +136,11 @@ msgid "" "Your avatar has been updated. %(avatar)s\n" "\n" "http://%(current_site)s%(avatar_url)s\n" -msgstr "Sua foto de perfil foi atualizada. %(avatar)s\n" +msgstr "" +"Sua foto de perfil foi atualizada. %(avatar)s\n" "\n" "http://%(current_site)s%(avatar_url)s\n" - #: templates/notification/avatar_updated/notice.html:2 #, fuzzy, python-format msgid "You have updated your avatar %(avatar)s." @@ -130,10 +148,22 @@ msgstr "" "%(avatar_creator)s atualizou a foto de perfil " "%(avatar)s." -#: templatetags/avatar_tags.py:45 +#: templatetags/avatar_tags.py:69 msgid "Default Avatar" msgstr "Foto de Perfil Padrão" +#: views.py:73 +msgid "Successfully uploaded a new avatar." +msgstr "Nova foto de perfil enviada com sucesso." + +#: views.py:111 +msgid "Successfully updated your avatar." +msgstr "Sua foto foi atualizada com sucesso." + +#: views.py:150 +msgid "Successfully deleted the requested avatars." +msgstr "As fotos de perfil selecionadas foram excluídas com sucesso." + #~ msgid "Avatar Updated" #~ msgstr "Foto de Perfil Atualizada" diff --git a/avatar/locale/ru/LC_MESSAGES/django.po b/avatar/locale/ru/LC_MESSAGES/django.po index a8cfe58..353d1fd 100644 --- a/avatar/locale/ru/LC_MESSAGES/django.po +++ b/avatar/locale/ru/LC_MESSAGES/django.po @@ -7,10 +7,11 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-17 00:31+0400\n" +"POT-Creation-Date: 2016-09-14 16:37+0200\n" "PO-Revision-Date: 2012-03-17 00:31+0400\n" "Last-Translator: frost-nzcr4 \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,50 +20,74 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "X-Poedit-SourceCharset: utf-8\n" -#: forms.py:33 -#, python-format -msgid "%(ext)s is an invalid file extension. Authorized extensions are : %(valid_exts_list)s" -msgstr "%(ext)s запрещённое расширение. Разрешённые расширения: %(valid_exts_list)s" +#: admin.py:26 +#, fuzzy +#| msgid "Avatar for %s" +msgid "Avatar" +msgstr "Аватар для %s" + +#: forms.py:24 models.py:84 models.py:97 +#, fuzzy +#| msgid "Default Avatar" +msgid "avatar" +msgstr "Аватар по умолчанию" #: forms.py:37 #, python-format -msgid "Your file is too big (%(size)s), the maximum allowed size is %(max_valid_size)s" -msgstr "Файл слишком большой (%(size)s), максимальный допустимый размер %(max_valid_size)s" +msgid "" +"%(ext)s is an invalid file extension. Authorized extensions are : " +"%(valid_exts_list)s" +msgstr "" +"%(ext)s запрещённое расширение. Разрешённые расширения: %(valid_exts_list)s" -#: forms.py:43 +#: forms.py:44 #, python-format -msgid "You already have %(nb_avatars)d avatars, and the maximum allowed is %(nb_max_avatars)d." -msgstr "У вас уже %(nb_avatars)d аватаров, максимально допустимо %(nb_max_avatars)d." +msgid "" +"Your file is too big (%(size)s), the maximum allowed size is " +"%(max_valid_size)s" +msgstr "" +"Файл слишком большой (%(size)s), максимальный допустимый размер " +"%(max_valid_size)s" -#: models.py:72 +#: forms.py:54 #, python-format -msgid "Avatar for %s" +msgid "" +"You already have %(nb_avatars)d avatars, and the maximum allowed is " +"%(nb_max_avatars)d." +msgstr "" +"У вас уже %(nb_avatars)d аватаров, максимально допустимо %(nb_max_avatars)d." + +#: forms.py:71 forms.py:84 +msgid "Choices" +msgstr "" + +#: models.py:77 +msgid "user" +msgstr "" + +#: models.py:80 +msgid "primary" +msgstr "" + +#: models.py:91 +msgid "uploaded at" +msgstr "" + +#: models.py:98 +#, fuzzy +#| msgid "Avatar for %s" +msgid "avatars" msgstr "Аватар для %s" -#: views.py:90 -msgid "Successfully uploaded a new avatar." -msgstr "Новый аватар загружен." - -#: views.py:128 -msgid "Successfully updated your avatar." -msgstr "Аватар обновлён." - -#: views.py:166 -msgid "Successfully deleted the requested avatars." -msgstr "Выбранные аватары удалены." - -#: templates/avatar/add.html:5 -#: templates/avatar/change.html:5 +#: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " msgstr "Ваш аватар:" -#: templates/avatar/add.html:8 -#: templates/avatar/change.html:8 +#: templates/avatar/add.html:8 templates/avatar/change.html:8 msgid "You haven't uploaded an avatar yet. Please upload one now." msgstr "Вы ещё не загружали аватар. Пожалуйста, загрузите его." -#: templates/avatar/add.html:12 -#: templates/avatar/change.html:19 +#: templates/avatar/add.html:12 templates/avatar/change.html:19 msgid "Upload New Image" msgstr "Загрузить новое изображение" @@ -76,24 +101,63 @@ msgstr "Выберите аватары, которые собираетесь #: templates/avatar/confirm_delete.html:8 #, python-format -msgid "You have no avatars to delete. Please upload one now." -msgstr "У вас нет аватаров. Загрузите его." +msgid "" +"You have no avatars to delete. Please upload one now." +msgstr "" +"У вас нет аватаров. Загрузите его." #: templates/avatar/confirm_delete.html:14 msgid "Delete These" msgstr "Удалить эти" +#: templates/notification/avatar_friend_updated/full.txt:1 +#, fuzzy, python-format +#| msgid "" +#| "%(avatar_creator)s has updated their avatar " +#| "%(avatar)s." +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" +"%(avatar_creator)s обновил свои аватары %(avatar)s." + #: templates/notification/avatar_friend_updated/notice.html:2 #, python-format -msgid "%(avatar_creator)s has updated their avatar %(avatar)s." -msgstr "%(avatar_creator)s обновил свои аватары %(avatar)s." +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s." +msgstr "" +"%(avatar_creator)s обновил свои аватары %(avatar)s." + +#: templates/notification/avatar_updated/full.txt:1 +#, python-format +msgid "" +"Your avatar has been updated. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" #: templates/notification/avatar_updated/notice.html:2 #, python-format msgid "You have updated your avatar %(avatar)s." msgstr "Вы обновили аватар %(avatar)s." -#: templatetags/avatar_tags.py:40 +#: templatetags/avatar_tags.py:69 msgid "Default Avatar" msgstr "Аватар по умолчанию" +#: views.py:73 +msgid "Successfully uploaded a new avatar." +msgstr "Новый аватар загружен." + +#: views.py:111 +msgid "Successfully updated your avatar." +msgstr "Аватар обновлён." + +#: views.py:150 +msgid "Successfully deleted the requested avatars." +msgstr "Выбранные аватары удалены." diff --git a/avatar/locale/zh_CN/LC_MESSAGES/django.po b/avatar/locale/zh_CN/LC_MESSAGES/django.po index c18d335..f4db91e 100644 --- a/avatar/locale/zh_CN/LC_MESSAGES/django.po +++ b/avatar/locale/zh_CN/LC_MESSAGES/django.po @@ -7,21 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: django-avatar\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-03-26 16:50+0800\n" +"POT-Creation-Date: 2016-09-14 16:37+0200\n" "PO-Revision-Date: 2014-03-26 17:08+0800\n" "Last-Translator: Bruce Yang \n" "Language-Team: Bruce Yang \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.5.7\n" -#: admin.py:19 +#: admin.py:26 msgid "Avatar" msgstr "头像" -#: forms.py:24 +#: forms.py:24 models.py:84 models.py:97 msgid "avatar" msgstr "头像" @@ -50,27 +51,45 @@ msgstr "您目前有 %(nb_avatars)d 个头像, 最多可以有 %(nb_max_avatars) msgid "Choices" msgstr "选项" -#: templates/avatar/add.html:6 templates/avatar/change.html:6 +#: models.py:77 +msgid "user" +msgstr "" + +#: models.py:80 +msgid "primary" +msgstr "" + +#: models.py:91 +msgid "uploaded at" +msgstr "" + +#: models.py:98 +#, fuzzy +#| msgid "avatar" +msgid "avatars" +msgstr "头像" + +#: templates/avatar/add.html:5 templates/avatar/change.html:5 msgid "Your current avatar: " msgstr "您当前的头像:" -#: templates/avatar/add.html:9 templates/avatar/change.html:9 +#: templates/avatar/add.html:8 templates/avatar/change.html:8 msgid "You haven't uploaded an avatar yet. Please upload one now." msgstr "您还没有上传任何头像,请现在上传一个吧。" -#: templates/avatar/add.html:13 templates/avatar/change.html:20 +#: templates/avatar/add.html:12 templates/avatar/change.html:19 msgid "Upload New Image" msgstr "上传新照片" -#: templates/avatar/change.html:15 +#: templates/avatar/change.html:14 msgid "Choose new Default" msgstr "选择默认" -#: templates/avatar/confirm_delete.html:6 +#: templates/avatar/confirm_delete.html:5 msgid "Please select the avatars that you would like to delete." msgstr "选择要删除的头像。" -#: templates/avatar/confirm_delete.html:9 +#: templates/avatar/confirm_delete.html:8 #, python-format msgid "" "You have no avatars to delete. Please 上传一个新头像。" -#: templates/avatar/confirm_delete.html:15 +#: templates/avatar/confirm_delete.html:14 msgid "Delete These" msgstr "删除" @@ -118,18 +137,18 @@ msgstr "" msgid "You have updated your avatar %(avatar)s." msgstr "您已经更新了头像 %(avatar)s." -#: templatetags/avatar_tags.py:51 +#: templatetags/avatar_tags.py:69 msgid "Default Avatar" msgstr "默认头像" -#: views.py:74 +#: views.py:73 msgid "Successfully uploaded a new avatar." msgstr "成功上传头像。" -#: views.py:110 +#: views.py:111 msgid "Successfully updated your avatar." msgstr "更新头像成功。" -#: views.py:148 +#: views.py:150 msgid "Successfully deleted the requested avatars." msgstr "成功删除头像。" diff --git a/avatar/migrations/0002_add_verbose_names_to_avatar_fields.py b/avatar/migrations/0002_add_verbose_names_to_avatar_fields.py new file mode 100644 index 0000000..ca12b15 --- /dev/null +++ b/avatar/migrations/0002_add_verbose_names_to_avatar_fields.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.1 on 2016-09-16 08:50 +from __future__ import unicode_literals + +import avatar.models +from django.conf import settings +import django.core.files.storage +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('avatar', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='avatar', + options={'verbose_name': 'avatar', 'verbose_name_plural': 'avatars'}, + ), + migrations.AlterField( + model_name='avatar', + name='avatar', + field=models.ImageField(blank=True, max_length=1024, storage=django.core.files.storage.FileSystemStorage(), upload_to=avatar.models.avatar_path_handler, verbose_name='avatar'), + ), + migrations.AlterField( + model_name='avatar', + name='date_uploaded', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='uploaded at'), + ), + migrations.AlterField( + model_name='avatar', + name='primary', + field=models.BooleanField(default=False, verbose_name='primary'), + ), + migrations.AlterField( + model_name='avatar', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user'), + ), + ] diff --git a/avatar/models.py b/avatar/models.py index 0d4d76b..e0dc527 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -72,16 +72,30 @@ def find_extension(format): class Avatar(models.Model): - user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL', 'auth.User')) - primary = models.BooleanField(default=False) - avatar = models.ImageField(max_length=1024, - upload_to=avatar_file_path, - storage=avatar_storage, - blank=True) - date_uploaded = models.DateTimeField(default=now) + user = models.ForeignKey( + getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), + verbose_name=_("user"), + ) + primary = models.BooleanField( + verbose_name=_("primary"), + default=False, + ) + avatar = models.ImageField( + verbose_name=_("avatar"), + max_length=1024, + upload_to=avatar_file_path, + storage=avatar_storage, + blank=True, + ) + date_uploaded = models.DateTimeField( + verbose_name=_("uploaded at"), + default=now, + ) class Meta: app_label = 'avatar' + verbose_name = _('avatar') + verbose_name_plural = _('avatars') def __unicode__(self): return _(six.u('Avatar for %s')) % self.user From 7f974b87c278ef009535271461b5e49686057a9a Mon Sep 17 00:00:00 2001 From: Raphael Lechner Date: Wed, 28 Dec 2016 20:45:00 +0100 Subject: [PATCH 103/119] Fix for django >= 1.10 The class django.core.management.NoArgsCommand is removed. --- avatar/management/commands/rebuild_avatars.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/avatar/management/commands/rebuild_avatars.py b/avatar/management/commands/rebuild_avatars.py index 9be08a8..2061946 100644 --- a/avatar/management/commands/rebuild_avatars.py +++ b/avatar/management/commands/rebuild_avatars.py @@ -1,14 +1,14 @@ -from django.core.management.base import NoArgsCommand +from django.core.management.base import BaseCommand from avatar.conf import settings from avatar.models import Avatar -class Command(NoArgsCommand): +class Command(BaseCommand): help = ("Regenerates avatar thumbnails for the sizes specified in " "settings.AVATAR_AUTO_GENERATE_SIZES.") - def handle_noargs(self, **options): + def handle(self, *args, **options): for avatar in Avatar.objects.all(): for size in settings.AVATAR_AUTO_GENERATE_SIZES: if options['verbosity'] != 0: From 57707e481e183b954a7bd565f918452b8397c486 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Fri, 14 Apr 2017 09:34:27 -0500 Subject: [PATCH 104/119] Update README.rst --- README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.rst b/README.rst index 59d927d..2026333 100644 --- a/README.rst +++ b/README.rst @@ -18,6 +18,10 @@ django-avatar :target: https://coveralls.io/github/grantmcconnaughey/django-avatar?branch=master :alt: Coverage +.. image:: https://lintly.com/gh/grantmcconnaughey/django-avatar/badge.svg + :target: https://lintly.com/gh/grantmcconnaughey/django-avatar/ + :alt: Lintly + Django-avatar is a reusable application for handling user avatars. It has the ability to default to Gravatar if no avatar is found for a certain user. Django-avatar automatically generates thumbnails and stores them to your default From 3f646d6f71247e005496e10df8050ea330a72a4e Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 27 May 2017 09:43:23 -0500 Subject: [PATCH 105/119] Update changelog for 4.0.0 --- CHANGELOG.rst | 6 ++++++ docs/index.txt | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f644c01..7cdef78 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,12 @@ Changelog ========= +* 4.0.0 (May 27, 2017) + * **Backwards incompatible:** Added ``AVATAR_PROVIDERS`` setting. Avatar providers are classes that return an avatar URL for a given user. + * Added ``verbose_name`` to ``Avatar`` model fields. + * Improved German translations. + * Fixed bug where ``rebuild_avatars`` would fail on Django 1.10+. + * 3.1.0 (September 10, 2016) * Added the ability to override templates using ``AVATAR_ADD_TEMPLATE``, ``AVATAR_CHANGE_TEMPLATE``, and ``AVATAR_DELETE_TEMPLATE``. * Added the ability to pass additional HTML attributes using the ``{% avatar %}`` template tag. diff --git a/docs/index.txt b/docs/index.txt index c054913..2049c08 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -164,8 +164,8 @@ appear on the site. Listed below are those settings: .. py:data:: AVATAR_PROVIDERS - Tuple of classes that are tried in the given order for returning avatar - URLs. + Tuple of classes that are tried in the given order for returning avatar + URLs. Defaults to:: ( @@ -175,9 +175,9 @@ appear on the site. Listed below are those settings: ) If you want to implement your own provider, it must provide a class method - ``get_avatar_url(user, size)``. + ``get_avatar_url(user, size)``. - .. py:class:: avatar.providers.GravatarAvatarProvider + .. py:class:: avatar.providers.PrimaryAvatarProvider Returns the primary avatar stored for the given user. From e02c8817832d20a9c140ffbacc02138c7ec3c4f5 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 27 May 2017 09:47:16 -0500 Subject: [PATCH 106/119] Update testing matrix --- .travis.yml | 21 ++++++++------------- CHANGELOG.rst | 4 ++++ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index d2a1f4f..5ecb869 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ language: python python: - 2.7 - - 3.3 - 3.4 - 3.5 + - 3.6 before_install: - pip install coveralls install: @@ -12,19 +12,14 @@ install: - pip install Django==${DJANGO} script: make test env: - - DJANGO=1.7.11 - - DJANGO=1.8.14 - - DJANGO=1.9.9 - - DJANGO=1.10.1 + - DJANGO=1.9.13 + - DJANGO=1.10.7 + - DJANGO=1.11.1 matrix: exclude: - - python: 3.3 - env: DJANGO=1.10.1 - - python: 3.3 - env: DJANGO=1.9.9 - - python: 3.5 - env: DJANGO=1.7.11 - - python: 3.5 - env: DJANGO=1.8.14 + - python: 3.6 + env: DJANGO=1.9.13 + - python: 3.6 + env: DJANGO=1.10.7 after_success: - coveralls diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7cdef78..26103b5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,10 @@ Changelog * Added ``verbose_name`` to ``Avatar`` model fields. * Improved German translations. * Fixed bug where ``rebuild_avatars`` would fail on Django 1.10+. + * Added Django 1.11 support. + * Added Python 3.6 support. + * Removed Django 1.7 and 1.8 support. + * Removed Python 3.3 support. * 3.1.0 (September 10, 2016) * Added the ability to override templates using ``AVATAR_ADD_TEMPLATE``, ``AVATAR_CHANGE_TEMPLATE``, and ``AVATAR_DELETE_TEMPLATE``. From 61a6d56d559529361ce8e2d4e3fda8c0cd8bd659 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 27 May 2017 09:47:48 -0500 Subject: [PATCH 107/119] Update PyPI classifiers --- setup.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index e31f577..4dffac8 100644 --- a/setup.py +++ b/setup.py @@ -29,19 +29,18 @@ setup( 'Framework :: Django', 'Intended Audience :: Developers', 'Framework :: Django', - 'Framework :: Django :: 1.7', - 'Framework :: Django :: 1.8', 'Framework :: Django :: 1.9', 'Framework :: Django :: 1.10', + 'Framework :: Django :: 1.11', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', ], keywords='avatar, django', author='Eric Florenzano', From c1f7abd2e4531077e4c04519fe03bbcf6bc4e195 Mon Sep 17 00:00:00 2001 From: Jannis Date: Tue, 17 Jan 2017 16:44:38 +0100 Subject: [PATCH 108/119] Add test for kwargs in template tag. --- avatar/utils.py | 4 ++-- tests/tests.py | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/avatar/utils.py b/avatar/utils.py index e0922f1..38db5b3 100644 --- a/avatar/utils.py +++ b/avatar/utils.py @@ -57,13 +57,13 @@ def cache_result(default_size=settings.AVATAR_DEFAULT_SIZE): return decorator def decorator(func): - def cached_func(user, size=None): + def cached_func(user, size=None, **kwargs): prefix = func.__name__ cached_funcs.add(prefix) key = get_cache_key(user, size or default_size, prefix=prefix) result = cache.get(key) if result is None: - result = func(user, size or default_size) + result = func(user, size or default_size, **kwargs) cache_set(key, result) return result return cached_func diff --git a/tests/tests.py b/tests/tests.py index e8c82f1..28f2501 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -210,6 +210,15 @@ class AvatarTests(TestCase): self.assertIn('', result) + def test_avatar_tag_works_with_kwargs(self): + upload_helper(self, "test.png") + avatar = get_primary_avatar(self.user) + + result = avatar_tags.avatar(self.user, title="Avatar") + + self.assertIn('test', result) + def test_default_add_template(self): response = self.client.get('/avatar/add/') self.assertContains(response, 'Upload New Image') From 51375039df42fcccf8c5d241b81e1831b617ff51 Mon Sep 17 00:00:00 2001 From: Jannis Date: Tue, 17 Jan 2017 15:39:42 +0100 Subject: [PATCH 109/119] Move alt attribute to kwargs. --- avatar/templates/avatar/avatar_tag.html | 2 +- avatar/templatetags/avatar_tags.py | 3 ++- tests/tests.py | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/avatar/templates/avatar/avatar_tag.html b/avatar/templates/avatar/avatar_tag.html index e6a3db2..e21ca17 100644 --- a/avatar/templates/avatar/avatar_tag.html +++ b/avatar/templates/avatar/avatar_tag.html @@ -1 +1 @@ -{{ alt }} \ No newline at end of file + \ No newline at end of file diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py index 1066b96..d3feee0 100644 --- a/avatar/templatetags/avatar_tags.py +++ b/avatar/templatetags/avatar_tags.py @@ -42,10 +42,11 @@ def avatar(user, size=settings.AVATAR_DEFAULT_SIZE, **kwargs): else: alt = six.text_type(user) url = avatar_url(user, size) + kwargs.update({'alt': alt}) + context = { 'user': user, 'url': url, - 'alt': alt, 'size': size, 'kwargs': kwargs, } diff --git a/tests/tests.py b/tests/tests.py index 28f2501..b1763f7 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -190,7 +190,7 @@ class AvatarTests(TestCase): result = avatar_tags.avatar(self.user.username) self.assertIn('', result) + self.assertIn('width="80" height="80" alt="test" />', result) def test_avatar_tag_works_with_user(self): upload_helper(self, "test.png") @@ -199,7 +199,7 @@ class AvatarTests(TestCase): result = avatar_tags.avatar(self.user) self.assertIn('', result) + self.assertIn('width="80" height="80" alt="test" />', result) def test_avatar_tag_works_with_custom_size(self): upload_helper(self, "test.png") @@ -208,7 +208,7 @@ class AvatarTests(TestCase): result = avatar_tags.avatar(self.user, 100) self.assertIn('', result) + self.assertIn('width="100" height="100" alt="test" />', result) def test_avatar_tag_works_with_kwargs(self): upload_helper(self, "test.png") From 6091dd90fee53841959392c29d181568e507aff2 Mon Sep 17 00:00:00 2001 From: Jannis Date: Thu, 2 Feb 2017 10:18:16 +0100 Subject: [PATCH 110/119] Add blank line to resolve failing PEP8 check. --- avatar/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/avatar/models.py b/avatar/models.py index e0dc527..d243200 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -59,6 +59,7 @@ def avatar_path_handler(instance=None, filename=None, size=None, ext=None): tmppath.append(os.path.basename(filename)) return os.path.join(*tmppath) + avatar_file_path = import_string(settings.AVATAR_PATH_HANDLER) From ccaafe492c1a85398f67ad5cf4d912e99f36c7b5 Mon Sep 17 00:00:00 2001 From: Jannis Date: Thu, 2 Feb 2017 11:28:09 +0100 Subject: [PATCH 111/119] Fix test for avatar tag. --- tests/tests.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index b1763f7..8ae0b98 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -215,9 +215,8 @@ class AvatarTests(TestCase): avatar = get_primary_avatar(self.user) result = avatar_tags.avatar(self.user, title="Avatar") - - self.assertIn('test', result) + html = 'test'.format(avatar.avatar_url(80)) + self.assertInHTML(html, result) def test_default_add_template(self): response = self.client.get('/avatar/add/') @@ -251,7 +250,7 @@ class AvatarTests(TestCase): response = self.client.get('/avatar/delete/') self.assertNotContains(response, 'like to delete.') self.assertContains(response, 'ALTERNATE DELETE TEMPLATE') - + # def testAvatarOrder # def testReplaceAvatarWhenMaxIsOne # def testHashFileName From 5ffa8a443a3f2ec01bca32f89c07ec5f85547707 Mon Sep 17 00:00:00 2001 From: Bruno Santeramo Date: Mon, 13 Feb 2017 16:00:54 +0100 Subject: [PATCH 112/119] Italian translation --- avatar/locale/it/LC_MESSAGES/django.mo | Bin 0 -> 3094 bytes avatar/locale/it/LC_MESSAGES/django.po | 161 +++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 avatar/locale/it/LC_MESSAGES/django.mo create mode 100644 avatar/locale/it/LC_MESSAGES/django.po diff --git a/avatar/locale/it/LC_MESSAGES/django.mo b/avatar/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..b555174b49a3e473bbe27dcb386ef0dd0e0224a6 GIT binary patch literal 3094 zcmb`J%a0UA9LGxmAEQx1^x%W!2WI0=*zTPj1lEQnF3WZS|nWgGayBkC|CmbVHo%<}+RWt6%-zH9zgy zd6VJuGX7u1|8M>QpRXPpav5K5u?f4q> zc6?j$d+-@N-vhCg{R(~tAAScrc>Wl|SHTU?fOAikdcFj`p4;Fn;9b!B^)u-G`U`vm z-0?JHZ-Ud{Bxu0>;1}Ra;9bzi>mKOicc@YNa}%7!^AF$^a4(GX@(z3t`~>v=Y*hRM zgedzP#2?#%p!)aE`{0g^^HuJ+S?(IaoiJ?Q+zL}3w*UCx@PRYOCi(G)J2axEib7%a zP*Kx*1tFU)V#Mb9T6Tr?)K-uZYjjeq@H}y>B2|(nMIxM_rM|F&Ehd6P++wZkd`PQ+ zT72h@)^$#6I!|IsMU2MHV5ZVAiJe$DZeh$ zJjJF&uR%W&Uu?npa9ddDE%Yf}`!M1;RUvyYLES!AJy9n-FU{3T6p2=PZA9}HL7)c} zJ|yGbZ*QM^-Ju!kSgE=d)`bgeBZo#%Z9pCLqVzgKsJfv-LNvrs)n}Cj z5&00BvXc;Fr!{qCkH*KwE&8Zwn-fK)-JcHsvdoE3NZDEC23DF?!LrQAl$&)n^xiSw zY;4i!_fg2fLL6KX#y4<82g9kb)wn1!ZCr5H_GBEK$a^+e(h)Tl&o2dYe!M_5IElFu zQM)yDBxtpRse?3iIBK;HwA!r}1cQrWReF^}xr0G#I%prERx4^x1+Bx7JHxFDmJC-m z@iQx;6DCI;UE<0K!&6PiI({Lv^}<`dl*=US>hw4^t6q-M4weK@Ba&`g(q6D}cH!*& z&}Z-QoW_v~#;j-X%3(%LW(k+-D4|e|6>jG8(y3s2DCdn{5hj>dT^&o+i)gw7&5KEH zcoLk_Cbbc%ta!9D?W0tFof%iOZ-%CtM;ljz(?Y?`!tqSEQynVd{G=@txM`9T@AafM z3eqIW=33SjT#G--Fjrd9om-SEPJRj%LtIc%OgyAB813~cj>8CZ4oN4gk)!`-ol~FM&X%HD2hI5O7z4->{)^?-m{auec&02)W zTRjpFm^c!#Z5PSFN_4B?R2~MWP$s3}xCBO0KVnR6$A6~k(QbrVt#diYPpK-3cWy<# zHi}cb7HaSW=MFIF;1~e>jp+alv(3t*8cs5@E3&Y$_(eTL11joaz79S F`v>(P#&!Sz literal 0 HcmV?d00001 diff --git a/avatar/locale/it/LC_MESSAGES/django.po b/avatar/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..3429a22 --- /dev/null +++ b/avatar/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,161 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: 3.1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-02-13 16:00+0200\n" +"PO-Revision-Date: 2013-08-27 00:21-0600\n" +"Last-Translator: Bruno Santeramo \n" +"Language-Team: it \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: po2mo.net\n" + +#: admin.py:26 +msgid "Avatar" +msgstr "Avatar" + +#: forms.py:24 models.py:84 models.py:97 +msgid "avatar" +msgstr "avatar" + +#: forms.py:37 +#, python-format +msgid "" +"%(ext)s is an invalid file extension. Authorized extensions are : " +"%(valid_exts_list)s" +msgstr "" +"%(ext)s non è una estensione valida. Le estensioni accettate sono : " +"%(valid_exts_list)s" + +#: forms.py:44 +#, python-format +msgid "" +"Your file is too big (%(size)s), the maximum allowed size is " +"%(max_valid_size)s" +msgstr "" +"Il file è troppo grande (%(size)s), la massima dimensione consentita " +"è %(max_valid_size)s" + +#: forms.py:54 +#, python-format +msgid "" +"You already have %(nb_avatars)d avatars, and the maximum allowed is " +"%(nb_max_avatars)d." +msgstr "" +"Hai già %(nb_avatars)d avatar, e il massimo numero consentito è " +"%(nb_max_avatars)d." + +#: forms.py:71 forms.py:84 +msgid "Choices" +msgstr "Opzioni" + +#: models.py:77 +msgid "user" +msgstr "utente" + +#: models.py:80 +msgid "primary" +msgstr "principale" + +#: models.py:91 +msgid "uploaded at" +msgstr "caricato su" + +#: models.py:98 +#, fuzzy +#| msgid "avatar" +msgid "avatars" +msgstr "avatar" + +#: templates/avatar/add.html:5 templates/avatar/change.html:5 +msgid "Your current avatar: " +msgstr "Il tuo attuale avatar è:" + +#: templates/avatar/add.html:8 templates/avatar/change.html:8 +msgid "You haven't uploaded an avatar yet. Please upload one now." +msgstr "Non hai ancora caricato un avatar. Per favore, carica uno adesso." + +#: templates/avatar/add.html:12 templates/avatar/change.html:19 +msgid "Upload New Image" +msgstr "Carica una Nuova Immagine" + +#: templates/avatar/change.html:14 +msgid "Choose new Default" +msgstr "Scegli un nuovo predefinito" + +#: templates/avatar/confirm_delete.html:5 +msgid "Please select the avatars that you would like to delete." +msgstr "Per favore, seleziona gli avatar che vuoi eliminare." + +#: templates/avatar/confirm_delete.html:8 +#, python-format +msgid "" +"You have no avatars to delete. Please upload one now." +msgstr "" +"Non hai avatar da eliminare. Per favore carica uno adesso." + +#: templates/avatar/confirm_delete.html:14 +msgid "Delete These" +msgstr "Elimina Questi" + +#: templates/notification/avatar_friend_updated/full.txt:1 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" +"%(avatar_creator)s ha aggiornato i suoi avatar %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_friend_updated/notice.html:2 +#, python-format +msgid "" +"%(avatar_creator)s has updated their avatar %(avatar)s." +msgstr "" +"%(avatar_creator)s ha aggiornato i suoi avatar %(avatar)s." + +#: templates/notification/avatar_updated/full.txt:1 +#, python-format +msgid "" +"Your avatar has been updated. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" +msgstr "" +"Il tuo avatar è stato aggiornato. %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" + +#: templates/notification/avatar_updated/notice.html:2 +#, python-format +msgid "You have updated your avatar %(avatar)s." +msgstr "Hai aggiornato il tuo avatar %(avatar)s." + +#: templatetags/avatar_tags.py:69 +msgid "Default Avatar" +msgstr "Avatar Predefinito" + +#: views.py:73 +msgid "Successfully uploaded a new avatar." +msgstr "Nuovo avatar caricato con successo" + +#: views.py:111 +msgid "Successfully updated your avatar." +msgstr "Il tuo avatar è stato aggiornato con successo." + +#: views.py:150 +msgid "Successfully deleted the requested avatars." +msgstr "Gli avatar selezionati sono stati eliminati con successo." From 6151c426b7e79ea71106c56b12ab8c2ac519edaf Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 27 May 2017 09:55:23 -0500 Subject: [PATCH 113/119] Update version 4.0.0 changelog --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 26103b5..61baf90 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,8 @@ Changelog * 4.0.0 (May 27, 2017) * **Backwards incompatible:** Added ``AVATAR_PROVIDERS`` setting. Avatar providers are classes that return an avatar URL for a given user. * Added ``verbose_name`` to ``Avatar`` model fields. + * Added the ability to override the ``alt`` attribute using the ``avatar`` template tag. + * Added Italian translations. * Improved German translations. * Fixed bug where ``rebuild_avatars`` would fail on Django 1.10+. * Added Django 1.11 support. From cf97804f238833b33148d77b89fc854ea06b0f6e Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sat, 27 May 2017 09:58:55 -0500 Subject: [PATCH 114/119] Bump version to 4.0.0 --- avatar/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avatar/__init__.py b/avatar/__init__.py index 7f5601d..d6497a8 100644 --- a/avatar/__init__.py +++ b/avatar/__init__.py @@ -1 +1 @@ -__version__ = '3.1.0' +__version__ = '4.0.0' From f8716937b0986b087ec3bb2220108f496a908538 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sun, 27 Aug 2017 08:45:45 -0500 Subject: [PATCH 115/119] Prevented creation of the new migrations with non-default DEFAULT_FILE_STORAGE --- avatar/migrations/0003_auto_20170827_1345.py | 21 ++++++++++++++++++ avatar/models.py | 23 +++++++++++++++----- 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 avatar/migrations/0003_auto_20170827_1345.py diff --git a/avatar/migrations/0003_auto_20170827_1345.py b/avatar/migrations/0003_auto_20170827_1345.py new file mode 100644 index 0000000..c85e774 --- /dev/null +++ b/avatar/migrations/0003_auto_20170827_1345.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-08-27 13:45 +from __future__ import unicode_literals + +import avatar.models +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('avatar', '0002_add_verbose_names_to_avatar_fields'), + ] + + operations = [ + migrations.AlterField( + model_name='avatar', + name='avatar', + field=avatar.models.AvatarField(), + ), + ] diff --git a/avatar/models.py b/avatar/models.py index d243200..ddf1ff3 100644 --- a/avatar/models.py +++ b/avatar/models.py @@ -72,6 +72,21 @@ def find_extension(format): return format +class AvatarField(models.ImageField): + + def __init__(self, *args, **kwargs): + super(AvatarField, self).__init__(*args, **kwargs) + + self.max_length = 1024 + self.upload_to = avatar_file_path + self.storage = avatar_storage + self.blank = True + + def deconstruct(self): + name, path, args, kwargs = super(models.ImageField, self).deconstruct() + return name, path, (), {} + + class Avatar(models.Model): user = models.ForeignKey( getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), @@ -81,12 +96,8 @@ class Avatar(models.Model): verbose_name=_("primary"), default=False, ) - avatar = models.ImageField( - verbose_name=_("avatar"), - max_length=1024, - upload_to=avatar_file_path, - storage=avatar_storage, - blank=True, + avatar = AvatarField( + verbose_name=_("avatar") ) date_uploaded = models.DateTimeField( verbose_name=_("uploaded at"), From 4abf3277a276bb3dfe69456b14238c4ad1950706 Mon Sep 17 00:00:00 2001 From: Duda Nogueira Date: Wed, 9 Aug 2017 09:00:39 -0300 Subject: [PATCH 116/119] Doc: Add url method to url to avoid error on django newer versions --- docs/index.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.txt b/docs/index.txt index 2049c08..181e101 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -48,7 +48,7 @@ that are required. A minimal integration can work like this: urlpatterns = [ # ... - (r'^avatar/', include('avatar.urls')), + url(r'^avatar/', include('avatar.urls')), ] 4. Somewhere in your template navigation scheme, link to the change avatar From dcabd11e43333bdfa20064957f27cc625d8ff88b Mon Sep 17 00:00:00 2001 From: Fabian Stehle Date: Wed, 12 Jul 2017 11:24:31 +0200 Subject: [PATCH 117/119] Fix invalid translations 'msgid' and 'msgstr' entries do not both end with '\n' which is mandatory according to specification from the 'msgfmt' manual: ``` The msgid and msgstr strings are studied and compared. It is considered abnormal if one string starts or ends with a newline while the other does not. ``` Besides all placeholders from the 'msgid' must be used in the 'mgstr'. --- avatar/locale/fr/LC_MESSAGES/django.po | 5 +++-- avatar/locale/ru/LC_MESSAGES/django.po | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/avatar/locale/fr/LC_MESSAGES/django.po b/avatar/locale/fr/LC_MESSAGES/django.po index 1b1f395..5459622 100644 --- a/avatar/locale/fr/LC_MESSAGES/django.po +++ b/avatar/locale/fr/LC_MESSAGES/django.po @@ -117,8 +117,9 @@ msgid "" "\n" "http://%(current_site)s%(avatar_url)s\n" msgstr "" -"%(avatar_creator)s a mis à jour son avatar %(avatar)s." +"%(avatar_creator)s a mis à jour son avatar %(avatar)s\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" #: templates/notification/avatar_friend_updated/notice.html:2 #, python-format diff --git a/avatar/locale/ru/LC_MESSAGES/django.po b/avatar/locale/ru/LC_MESSAGES/django.po index 353d1fd..feb2b22 100644 --- a/avatar/locale/ru/LC_MESSAGES/django.po +++ b/avatar/locale/ru/LC_MESSAGES/django.po @@ -121,8 +121,9 @@ msgid "" "\n" "http://%(current_site)s%(avatar_url)s\n" msgstr "" -"%(avatar_creator)s обновил свои аватары %(avatar)s." +"%(avatar_creator)s обновил свои аватары %(avatar)s.\n" +"\n" +"http://%(current_site)s%(avatar_url)s\n" #: templates/notification/avatar_friend_updated/notice.html:2 #, python-format From dcc472a1e262b1f8a8ae1df80ba6105f926020c3 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sun, 27 Aug 2017 08:51:18 -0500 Subject: [PATCH 118/119] Document AVATAR_MAX_AVATARS_PER_USER --- docs/index.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/index.txt b/docs/index.txt index 181e101..3303e21 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -156,6 +156,11 @@ appear on the site. Listed below are those settings: .. py:data:: AVATAR_MAX_SIZE File size limit for avatar upload. Default is ``1024 * 1024`` (1 MB). + gravatar in ``user.gravatar``. Defaults to ``email``. + +.. py:data:: AVATAR_MAX_AVATARS_PER_USER + + The maximum number of avatars each user can have. Default is ``42``. .. py:data:: AVATAR_PATH_HANDLER From 4eaf6f8f1ecc09851ff4e627557c8779c1ea6ef3 Mon Sep 17 00:00:00 2001 From: Grant McConnaughey Date: Sun, 27 Aug 2017 08:53:30 -0500 Subject: [PATCH 119/119] Document AVATAR_CLEANUP_DELETED --- docs/index.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/index.txt b/docs/index.txt index 3303e21..cdc6526 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -212,6 +212,12 @@ appear on the site. Listed below are those settings: The directory under ``MEDIA_ROOT`` to store the images. If using a non-filesystem storage device, this will simply be appended to the beginning of the file name. Defaults to ``avatars``. + PIL. Defaults to ``Image.ANTIALIAS``. + +.. py:data:: AVATAR_CLEANUP_DELETED + + ``True`` if the avatar image files should be deleted when an avatar is + deleted from the database. Defaults to ``False``. .. py:data:: AVATAR_ADD_TEMPLATE