From 902a088ba0a2fe89f015b9be8ffdf70b1389d785 Mon Sep 17 00:00:00 2001 From: Gustavo Veloso Date: Sun, 20 Feb 2011 20:10:47 -0300 Subject: [PATCH] =?UTF-8?q?3=C2=BA=20sprint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database.db | Bin 43008 -> 44032 bytes settings.py | 8 ++- subscription/admin.py | 38 ++++++++++++- subscription/forms.py | 51 +++++++++++++++++- subscription/models.py | 10 ++-- subscription/validators.py | 13 +++++ subscription/views.py | 2 +- templates/admin/subscription/change_list.html | 13 +++++ templates/master.html | 3 +- urls.py | 2 +- 10 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 subscription/validators.py create mode 100644 templates/admin/subscription/change_list.html diff --git a/database.db b/database.db index 1c033a00543665514618b6bfff230f7640aa0fc7..ab3cab7a8b13fd424d4c82ff64f93158efd05e16 100644 GIT binary patch delta 2010 zcmah}YfMvT7(U;5TY5Zc2g;>|LOp;u8MO4A_Rt=TAr%XPr3i9q*#+C4Rw`{z1BH!5 z!Qe zetF(&-|u~&Q+LQyUz6vJ+xrQEXi~oGN59-`L;dNa=RjLmt$;>@BFf6}&rk(B;Ynt@ z_9vhTlYv%X6Pm*s%29-_p-X5kEw`bO8Wq}$XfYfMr@~|L=&{K_Dk>$$qf;qqa@Mq_ z4UGp9$2Mzgs#J(abU+k0IaX)B+{V73N)eFCY*$5~6f4=~ZAeQPbvoM=Lda#qCmg;8 z&dRVt8}Ddid5f)8;9KpSm1WIV&TMrstO8rxtj^0$mDWI$cM13oZoyS}2WG$zZZML6 zl6TYc$E3N5Rue6HbD@4F{|Ba|>C|`u&4c)l&YB&2C^b>v(9oTj3Qb0Dd~jn`!nIun z?C!d5pn)a80}tR+_z}K*|L5B>POA8djxA$rE$v{-BV}g{BW^KSE*AviJ+8#Qu3Fy`~!)98!*kw$4PbX>5xm{Bb=2N zxDaaUT@S13eMHZ`c~>6xa|qJnQ3n#{FC>7K{(P z=86p^N4t{a!MHf%iF;>)iGkU`NcVKkzJrhYN4%4xBm4v%n&rJgZXgzP&u{Q%hrB+n zlNGzhBcjh63&n)w=s~yp$g7>KC+_F`gW~aCZaCh1yfZ#}AU5IUdM5lMofEW|>$Z6h zgsh{3-igrzZjN3X1e@8~`gBBEZBB>7LBoBe1y=~TqFk~kQ=xhf8h1f2`o9K{igm-X zTzkP@lqvE(270ZX*;vY;u0YvHE?`z1L=<7Hx9MC6e|E-Ps!S@U45PKp?yxwW4m-;c zm(Lba^ejQl61T`xFuN>A$^LTXr4FmA&af4@Z>bqoXHG1gMMvcsy+$tx=!_=!___Jn zv@~0zH5~(P*PxpjbnW-JnYyiwa7mMOFpx}+B?9qq9WxV{RCac956AP3g)wTT8RgU! zw&B0clwh%FSj5YV(2*|TZ&_yMTMTMKK(>xRf?4B0 zW&ZOX}-oUG2gGPa_+P^QwVP?SJX zQcb=OeQDW`K(4IBH@z-Yi>W?8Ri)7%5|Hf1x4qT)T%QTmD{uq;yw3shZX@R72hlD( z7av2__+h*oH7NH+MO%um#w+p3MDa?pqX=Q?3041o%pYn3jFq}9-CJg}V&xAT^^s_`2k#0UiRO%a0Sd-wumTP zx0WoM20TmLgAY&=jV3Ck$-;clB|d609$bPUdoX)(iN+YmgEKRp!luK-cyiCV_x#TJ zzVm&*?|1I(2Ay4}^Y+pRA*6x#N6os>s6ZrpGKJN2v>i)(v~q>1q7B6Pw# z^cng!_UCFtbrf~OUN(JN0UKL6-HH0XG8Rt-VITV})dS^BNC%;ke>>SkS~FXC(twu; zUZTHc^}Cd99ji8Q?B@kNIg0@@p#9}$KyRy5i#7_5)V(cy&CRrf7Y}^ zl;RRS4=MCWZdsBPNy?W2aFgIB#cR1z!>0&s3wo{d5Vphrg#wuq2IF=ev5y(2c^w^? z>zm0KR<9NcW|@EtoAff8ah|UL>UCE3ar!9O*#~p=Y&~sccQYmI_FUQC$;8l^{?XWh zdfi=NtavF1dW5Z{9qe%0!qRi)P{l1`^er2EH={x|pV-(d%L2QTIm~%3UiLuELrmpd zzqi~74))b@^Ri*Sq!4h8;2KZtBP=<_bLFiCjKqFWu>{$Te%GEIRmoC7R@{=;tEs-# zlZAq*myllg5Pqkj1-;Gm_6v4n#gQX$p_X-pHK@&93=3c|)pzY@pLcZPfvzh4_Ok3q zrQzUtshZs!X#^*`5h~A>j!wXK*(oj(T*pNo$`zb((;^ZCD7J&;k%<2ZM0Cr3MfS=d zNUf8JxS zve?0PSu|J+hzDHxGX`R@T?gd8ONwYhOmPw73Z^(i=a8k|m=P%6BX}S0apXs|6(Ii? z(CrcO`BAz>aF%Z6FB0m4gI!qiu%?WIeZQn~MLfZ^@)Y}GsfG<^8q9f_?s8|&I}*0t G3Gf#K?Mx#8 diff --git a/settings.py b/settings.py index b47243f..07511c0 100644 --- a/settings.py +++ b/settings.py @@ -1,5 +1,6 @@ # Django settings for eventex project. +ON_HERIKE = False DEBUG = True TEMPLATE_DEBUG = DEBUG @@ -7,7 +8,11 @@ PROJECT_DIR = os.path.dirname(__file__) -EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +if ON_HERIKE: + EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +else: + EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + EMAIL_HOST = 'localhost' EMAIL_HOST_PASSWORD = '' EMAIL_HOST_USER = '' @@ -105,6 +110,7 @@ 'subscription', # Uncomment the next line to enable the admin: 'django.contrib.admin', + 'south', # Uncomment the next line to enable admin documentation: # 'django.contrib.admindocs', ) diff --git a/subscription/admin.py b/subscription/admin.py index 93f93a0..28ab5a4 100644 --- a/subscription/admin.py +++ b/subscription/admin.py @@ -1,18 +1,52 @@ +# encoding: utf-8 import datetime from django.contrib import admin from subscription.models import Subscription +from django.utils.translation import ugettext as _ +from django.utils.translation import ungettext +from django.http import HttpResponse +from django.conf.urls.defaults import patterns, url class SubscriptionAdmin(admin.ModelAdmin): - list_display = ('name', 'email', 'phone', 'created_at', 'subscribed_today') + list_display = ('name', 'email', 'phone', 'created_at', 'subscribed_today', 'paid') date_hierarchy = 'created_at' search_fields = ('name', 'email', 'phone', 'cpf', 'created_at') - list_filter = ['created_at'] + list_filter = ['created_at', 'paid'] + + actions = ['mark_as_paid'] def subscribed_today(self, obj): return obj.created_at.date() == datetime.date.today() subscribed_today.short_description = 'Inscrito hoje?' subscribed_today.boolean = True + + def mark_as_paid(self, request, queryset): + count = queryset.update(paid=True) + msg = ungettext ( + u'%(count)d inscrição foi marcada como paga.', + u'%(count)d inscrições foram marcadas como pagas.', + count) % {'count': count} + self.message_user(request, msg) + + mark_as_paid.short_description = _(u'Marcar como pagas') + + def export_subscriptions(self, request): + subscriptions = self.model.objects.all() + rows = [','.join([s.name, s.email]) for s in subscriptions] #list comprehension + response = HttpResponse('\r\n'.join(rows)) + response.mimetype = 'text/csv' + response['Content-Disposition'] = 'attachment; filename=inscritos.csv' + + return response + + def get_urls(self): + default_urls = super(SubscriptionAdmin, self).get_urls() + new_urls = patterns('', + url(r'^exportar-inscricoes/$', self.admin_site.admin_view(self.export_subscriptions), + name='export_subscriptions')) + + return new_urls + default_urls admin.site.register(Subscription, SubscriptionAdmin) diff --git a/subscription/forms.py b/subscription/forms.py index 60b5aed..7c97310 100644 --- a/subscription/forms.py +++ b/subscription/forms.py @@ -1,7 +1,56 @@ +# encoding: utf-8 + from django import forms from subscription.models import Subscription +from django.utils.translation import ugettext as _ +from subscription import validators +from django.core.validators import EMPTY_VALUES + +class PhoneWidget(forms.MultiWidget): + def __init__(self, attrs=None): + widgets = ( + forms.TextInput(attrs=attrs), + forms.TextInput(attrs=attrs)) + super(PhoneWidget, self).__init__(widgets, attrs) + + def decompress(self, value): + if value: + return value.split('‐') + return [None, None] + +class PhoneField(forms.MultiValueField): + + widget = PhoneWidget + + def __init__(self, *args, **kwargs): + fields = (forms.IntegerField(), forms.IntegerField()) + super(PhoneField, self).__init__(fields, *args, **kwargs) + + def compress(self, data_list): + if data_list: + if data_list[0] in EMPTY_VALUES: + raise forms.ValidationError(_(u'DDD inválido.')) + if data_list[1] in EMPTY_VALUES: + raise forms.ValidationError(_(u'Número inválido.')) + return '%s‐%s' % tuple(data_list) + return "" class SubscriptionForm(forms.ModelForm): + + phone = PhoneField(required=False) + class Meta: model = Subscription - exclude= ("created_at",) + exclude= ('created_at', 'paid') + + def clean(self): + super(SubscriptionForm, self).clean() + if not self.cleaned_data.get('email') and not self.cleaned_data.get('phone'): + raise forms.ValidationError(_(u'Você deve informar pelo menos o e-mail ou o telefone.')) + return self.cleaned_data + + + + + + diff --git a/subscription/models.py b/subscription/models.py index ec8116f..0defa40 100644 --- a/subscription/models.py +++ b/subscription/models.py @@ -1,15 +1,17 @@ -#coding: utf-8 +# encoding: utf-8 from django.db import models +from subscription import validators # Create your models here. class Subscription(models.Model): name = models.CharField('Nome', max_length=100) - cpf = models.CharField('CPF', max_length=11, unique=True) - email = models.EmailField('E-mail', unique=True) + cpf = models.CharField('CPF', max_length=11, unique=True, validators=[validators.CpfValidator]) + email = models.EmailField('E-mail', unique=True, blank=True) phone = models.CharField('Telefone', max_length=20, blank=True) created_at = models.DateTimeField('Data inscrição', auto_now_add=True) + paid = models.BooleanField('Pagou?', default=False) def __unicode__(self): return self.name @@ -18,3 +20,5 @@ class Meta: ordering = ["created_at"] verbose_name = u"Inscrição" verbose_name_plural = u"Inscrições" + + diff --git a/subscription/validators.py b/subscription/validators.py new file mode 100644 index 0000000..eaae30c --- /dev/null +++ b/subscription/validators.py @@ -0,0 +1,13 @@ +# encoding: utf-8 +from django.utils.translation import ugettext as _ +from django.core.exceptions import ValidationError + +def CpfValidator(value): + if not value.isdigit(): + raise ValidationEror(_(u'O CPF deve conter apenas números')) + if len(value) != 11: + raise ValidationError(_(u'O CPF deve conter 11 dígitos')) + + + + diff --git a/subscription/views.py b/subscription/views.py index 3e8b553..3ee00f6 100644 --- a/subscription/views.py +++ b/subscription/views.py @@ -1,4 +1,4 @@ -# coding: utf-8 +# encoding: utf-8 # Create your views here. from django.http import HttpResponseRedirect diff --git a/templates/admin/subscription/change_list.html b/templates/admin/subscription/change_list.html new file mode 100644 index 0000000..a01144e --- /dev/null +++ b/templates/admin/subscription/change_list.html @@ -0,0 +1,13 @@ +{% extends 'admin/change_list.html' %} +{% block object-tools %} + + +{{ block.super }} +{% endblock object-tools %} + diff --git a/templates/master.html b/templates/master.html index 2e9b4ed..04771ca 100644 --- a/templates/master.html +++ b/templates/master.html @@ -28,10 +28,9 @@

EventeX