def script_polls(request): columns = [('Name', True, 'name', SimpleSorter()), ( 'Question', True, 'question', SimpleSorter(), ), ( 'Start Date', True, 'start_date', SimpleSorter(), ), ('Closing Date', True, 'end_date', SimpleSorter()), ('', False, '', None)] return generic(request, model=Poll, queryset=get_script_polls, objects_per_page=10, selectable=False, partial_row='ureport/partials/polls/poll_admin_row.html', base_template='ureport/poll_admin_base.html', paginator_template='ureport/partials/new_pagination.html', paginator_func=ureport_paginate, results_title='Polls', sort_column='start_date', auto_reg=True, sort_ascending=False, columns=columns)
def flag_categories(request, name): group = get_object_or_404(Group, name=name) if get_access(request) and request.user not in group.user_set.all(): return render(request, '403.html', status=403) access = group.access_set.all()[0] flags = access.flags.all() flagged_messages = MessageFlag.objects.filter(flag__in=flags, message__connection__contact__reporting_location__name__in=access.allowed_locations) if request.GET.get('export', None): data = flagged_messages.filter( message__connection__contact__reporting_location__name__in=access.allowed_locations).values_list( 'message__connection_id', 'message__text', 'flag__name', 'message__date', 'message__connection__contact__reporting_location__name') headers = ['Identifier', 'Message', 'Flag', 'Date', 'District'] return ExcelResponse(data=data, headers=headers) return generic( request, model=MessageFlag, queryset=flagged_messages, objects_per_page=10, results_title='Flagged Messages', selectable=False, partial_row='ureport/partials/messages/flagged_message_row.html' , base_template='ureport/flagged_message_base.html', columns=[('Identifier', True, 'message__connection_id', SimpleSorter()), ('Message', True, 'message__text', SimpleSorter()), ('Date', True, 'message__date', SimpleSorter()), ('Flags', False, 'message__flagged', None)], sort_column='date', sort_ascending=False, all_flags=flags, go_to_dashboards=True )
def view_messages(request): context = {} columns = [ ('Name', True, 'title', SimpleSorter()), ('Parish', True, 'decription', SimpleSorter()), ('Mobile', True, 'questions__name', SimpleSorter()), ('Status', True, 'enabled', SimpleSorter()), ('Submissions', False, '', ''), ('Last Submission', False, '', ''), ] messages = Message.objects.filter(connection__pk__in=Reporter.objects. values("connection")).order_by("-pk") return generic(request, model=Message, queryset=Reporter.objects.all(), filter_forms=[], action_forms=[], objects_per_page=25, partial_row='ntds/partials/reporter_row.html', base_template='ntds/reporter_base.html', columns=columns, sort_column='pk', sort_ascending=False, current='survey')
def view_autoreg_rules(request): columns = [( 'Group', True, 'group__name', SimpleSorter(), ), ( 'Rule', True, 'rule', SimpleSorter(), ), ( 'Words', True, 'values', SimpleSorter(), ), ( 'Closed', True, 'closed', SimpleSorter(), ), ('', False, '', None)] qs = AutoregGroupRules.objects.all() return generic( request, model=AutoregGroupRules, queryset=qs, objects_per_page=20, results_title='Group Rules', selectable=False, partial_row='ureport/partials/group_row.html', base_template='ureport/group_base.html', columns=columns, )
def reports(request): columns = [ ('Name', True, 'title', SimpleSorter()), ('Parish', True, 'decription', SimpleSorter()), ('Mobile', True, 'questions__name', SimpleSorter()), ('Status', True, 'enabled', SimpleSorter()), ('Submissions', False, '', ''), ('Last Submission', False, '', ''), ] filter_forms = [FreeSearchForm, MultipleDistictFilterForm] action_forms = [DownloadForm, SendTextForm] return generic( request, model=Reporter, queryset=Reporter.objects.all(), filter_forms=filter_forms, action_forms=action_forms, objects_per_page=25, partial_row='ntds/partials/report_row.html', base_template='ntds/report_base.html', columns=columns, sort_column='pk', sort_ascending=False, )
def view_flagged_with(request, pk): flag = get_object_or_404(Flag, pk=pk) access = get_access(request) if access and not flag in access.flags.all(): return render(request, '403.html', status=403) messages = flag.get_messages() if request.GET.get('export', None): export_data = messages.values_list('text', 'connection_id', 'date', 'connection__contact__reporting_location__name') headers = ['Message', 'Identifier', 'Date', 'District'] return ExcelResponse(data=export_data, headers=headers) return generic( request, model=Message, queryset=messages, objects_per_page=25, partial_row='ureport/partials/contacts/contacts_row_flag.html', base_template='ureport/view_flagged_with_base.html', results_title='Messages Flagged With %s' % flag.name, columns=[('Message', True, 'text', SimpleSorter()), ('Identifier', True, 'connection_id', SimpleSorter()), ('Date', True, 'date', SimpleSorter()), ('Type', True, 'application', SimpleSorter())], sort_column='date', sort_ascending=False, )
def comfirmmessages(request, key): messages = Message.objects.filter( details__attribute__name=key).order_by('-date') partial_row = 'ureport/partials/messages/message_row.html' base_template = 'ureport/comfirmbase.html' paginator_template = 'ureport/partials/new_pagination.html' columns = [('Text', True, 'text', SimpleSorter()), ('Date', True, 'date', SimpleSorter())] if request.method == "POST": res = dict(request.POST)['results'] messages = Message.objects.filter(pk__in=res).update(status="Q") return HttpResponseRedirect("/reporter/") return generic( request, model=Message, queryset=messages, objects_per_page=25, partial_row=partial_row, base_template=base_template, results_title="Messages To be Sent. Please Comfirm to sent .", paginator_template=paginator_template, paginator_func=ureport_paginate, columns=columns, sort_column='date', key=key, sort_ascending=False, )
def flagged_messages(request): all_flags = Flag.objects.all() if request.GET.get('export', None): flaggedmessages = MessageFlag.objects.exclude(flag=None) data = flaggedmessages.values_list( 'message__connection_id', 'message__text', 'flag__name', 'message__date', 'message__connection__contact__reporting_location__name') headers = ['Identifier', 'Message', 'Flag', 'Date', 'District'] return ExcelResponse(data=data, headers=headers) return generic( request, model=MessageFlag, queryset=get_flagged_messages, objects_per_page=10, results_title='Flagged Messages', selectable=False, partial_row='ureport/partials/messages/flagged_message_row.html', base_template='ureport/flagged_message_base.html', columns=[('Identifier', True, 'message__connection_id', SimpleSorter()), ('Message', True, 'message__text', SimpleSorter()), ('Date', True, 'message__date', SimpleSorter()), ('Flags', False, 'message__flagged', None)], sort_column='date', sort_ascending=False, all_flags=all_flags, )
def autoreg_messages(request): access = get_access(request) filter_forms = [SearchInMessagesForm, DistictFilterMessageForm] action_forms = [ReplyTextForm, BlacklistForm2] partial_row = 'ureport/partials/messages/message_row.html' base_template = 'ureport/contact_message_base.html' paginator_template = 'ureport/partials/new_pagination.html' columns = [('Text', True, 'text', SimpleSorter()), ('Identifier', True, 'connection__pk', SimpleSorter()), ('Date', True, 'date', SimpleSorter()), ('Type', True, 'application', SimpleSorter()), ('Response', False, 'response', None)] queryset = get_autoreg_messages(request=request) if access: queryset = queryset.filter( connection__contact__groups__in=access.groups.all()) return generic( request, model=Message, queryset=queryset, filter_forms=filter_forms, action_forms=action_forms, objects_per_page=25, partial_row=partial_row, results_title="Autoreg Messages", base_template=base_template, paginator_template=paginator_template, paginator_func=ureport_paginate, columns=columns, sort_column='date', sort_ascending=False, )
def ureport_polls(request): access = get_access(request) columns = [('Name', True, 'name', SimpleSorter()), ( 'Question', True, 'question', SimpleSorter(), ), ( 'Start Date', True, 'start_date', SimpleSorter(), ), ('Closing Date', True, 'end_date', SimpleSorter()), ('', False, '', None)] queryset = get_polls(request=request) if access: queryset = queryset.filter(user=access.user) return generic(request, model=Poll, queryset=queryset, objects_per_page=10, selectable=False, partial_row='ureport/partials/polls/poll_admin_row.html', base_template='ureport/poll_admin_base.html', paginator_template='ureport/partials/new_pagination.html', results_title='Polls', paginator_func=ureport_paginate, sort_column='start_date', sort_ascending=False, columns=columns)
def view_responses(req, poll_id): poll = get_object_or_404(Poll, pk=poll_id) access = get_access(req) if access and not poll.user == access.user: return render(req, '403.html', status=403) script_polls = \ ScriptStep.objects.exclude(poll=None).values_list('poll', flat=True) response_rates = {} if poll.pk in script_polls: responses = poll.responses.order_by('-date') log.info("[reponses] 1 - %s " % responses) else: responses = poll.responses.all() responses = responses.order_by('-date') log.info("[reponses] 3 - %s " % responses) for group in req.user.groups.all(): try: contact_count = \ poll.contacts.filter(groups__in=[group]).distinct().count() response_count = \ poll.responses.filter(contact__groups__in=[group]).distinct().count() response_rates[str(group.name)] = [contact_count] response_rates[str(group.name)].append(response_count) response_rates[str(group.name)].append(response_count * 100.0 / contact_count) except ZeroDivisionError: response_rates.pop(group.name) typedef = Poll.TYPE_CHOICES[poll.type] # columns = [('Sender', False, 'sender', None)] # for (column, style_class, sortable, db_field, sorter) in \ # typedef['report_columns']: # columns.append((column, sortable, db_field, sorter)) columns = ((_('Date'), True, 'date', SimpleSorter()), (_('Text'), True, 'poll__question', SimpleSorter()), (_('Category'), True, 'categories__category', SimpleSorter())) return generic( req, model=Response, response_rates=response_rates, queryset=responses, objects_per_page=25, selectable=True, partial_base='ureport/partials/polls/poll_partial_base.html', base_template='ureport/responses_base.html', paginator_template='ureport/partials/new_pagination.html', paginator_func=ureport_paginate, row_base=typedef['view_template'], action_forms=[ AssignToPollForm, AssignResponseGroupForm, ReplyTextForm, DeleteSelectedForm ], filter_forms=[SearchResponsesForm], columns=columns, partial_row='ureport/partials/polls/response_row.html', poll_id=poll_id, )
def view_submissions(request, xform_pk): xform = get_object_or_404(XForm, pk=xform_pk) return generic(\ request, \ model=XFormSubmission, \ queryset=xform.submissions.all().order_by('-created'), \ objects_per_page=25, \ base_template='kit/submissions_base.html', \ partial_row='kit/partials/reports/submission_row.html', \ results_title='Last Reporting Period Results', \ columns=[('Reporter', True, 'message__connection__contact__name', SimpleSorter(),), \ ('Location', True, 'message__connection__contact__reporting_location__name', SimpleSorter(),), \ ('Report', True, 'raw', SimpleSorter(),), \ ('Date', True, 'created', SimpleSorter(),), \ ('Approved', True, 'approved', SimpleSorter(),), \ ('', False, '', None,)], \ sort_column='message__connection__contact__healthproviderbase__healthprovider__facility__name', \ )
def poll_dashboard(request): columns = [ (_('Name'), True, 'name', SimpleSorter()), ( _('Question'), True, 'question', SimpleSorter(), ), ( _('Start Date'), True, 'start_date', SimpleSorter(), ), ( _('# Participants'), False, 'participants', None, ), ( _('Visuals'), False, 'visuals', None, ), ] return generic(request, model=Poll, queryset=get_polls, results_title='Polls', objects_per_page=10, partial_row='ureport/partials/dashboard/poll_row.html', partial_header= 'ureport/partials/dashboard/partial_header_dashboard.html', base_template='ureport/dashboard.html', paginator_template='ureport/partials/new_pagination.html', paginator_func=ureport_paginate, selectable=False, sort_column='start_date', columns=columns)
def ussd_manager(request): ussd_contacts = Contact.objects.filter(groups__name='equatel') ussd_conns = Connection.objects.filter(contact__in=ussd_contacts) messages = \ Message.objects.filter(connection__in=ussd_conns).order_by('-date' ) return generic( request, model=Message, queryset=messages, objects_per_page=25, partial_row='contact/partials/message_row.html', base_template='ureport/ussd_messages_base.html', results_title='Ussd Messages', columns=[('Message', True, 'text', SimpleSorter()), ('Date', True, 'date', SimpleSorter()), ('Type', True, 'application', SimpleSorter())], sort_column='date', sort_ascending=False, )
def manage_reporters(request): queryset = Reporter.objects.all(), columns = [ ('Name', True, 'title', SimpleSorter()), ('Parish', True, 'decription', SimpleSorter()), ('Subcounty', True, 'decription', SimpleSorter()), ('District', True, 'decription', SimpleSorter()), ('Mobile', True, 'questions__name', SimpleSorter()), ('Status', True, 'enabled', SimpleSorter()), ('Submissions', False, '', ''), ] filter_forms = [FreeSearchForm, MultipleDistictFilterForm] action_forms = [DownloadForm, SendTextForm] if not request.POST.get("page_num") and request.method == "POST": return ExcelResponse(queryset) return generic( request, model=Reporter, queryset=queryset, filter_forms=filter_forms, action_forms=action_forms, objects_per_page=25, partial_row='ntds/partials/reporter_row.html', base_template='ntds/reporter_base.html', columns=columns, sort_column='pk', sort_ascending=False, )
def view_messages(request): #filter_forms = [] #action_forms = [] partial_row = 'mission/partials/messages_row.html' base_template = 'mission/partials/messages_base.html' paginator_template = 'mission/partials/pagination.html' columns = [ ('Message', True, 'text', SimpleSorter()), ('Type', True, 'type', SimpleSorter()), ('sender', True, 'sender__username', SimpleSorter()), ('Destination', True, 'identifier', SimpleSorter()), ('Date', True, 'created', SimpleSorter()), ('Status', True, 'delivered', SimpleSorter()), ] return generic( request, model=Message, queryset=Message.objects.all(), objects_per_page=25, partial_row=partial_row, results_title="Messages", title="All SMS and Emails", base_template=base_template, paginator_template=paginator_template, paginator_func=paginate, columns=columns, sort_column='pk', show_unfiltered=False, sort_ascending=False, )
def cloud_dashboard(request, name): name = name.replace("_", " ") category = get_object_or_404(IbmCategory, name__iexact=name) tags = get_category_tags(category=category) columns = [('Identifier', True, 'message__connection_id', SimpleSorter()), ('Text', True, 'msg__text', SimpleSorter()), ('Date', True, 'msg__date', SimpleSorter()), ('Score', True, 'score', SimpleSorter()), ('Category', True, 'category', SimpleSorter(),), ('Action', True, 'action', SimpleSorter(),), ('Rating', False, '', None)] return generic( request, model=IbmMsgCategory, queryset=IbmMsgCategory.objects.filter(category=category, msg__direction='I', score__gte=0.5), objects_per_page=20, results_title='Classified Messages', partial_row='message_classifier/message_row.html', base_template='message_classifier/message_classifier_cloud_base.html', paginator_template='ureport/partials/new_pagination.html', paginator_func=ureport_paginate, columns=columns, sort_column='msg__date', sort_ascending=False, tags=tags, ibm_categories=IbmCategory.objects.all() )
def view_submissions(request, reporter=None): columns = [ ('Name', True, 'title', SimpleSorter()), ('Parish', True, 'decription', SimpleSorter()), ('Mobile', True, 'questions__name', SimpleSorter()), ('Status', True, 'enabled', SimpleSorter()), ('Submissions', False, '', ''), ('Last Submission', False, '', ''), ] return generic(request, model=XFormSubmission, queryset=XFormSubmission.objects.all(), filter_forms=[], action_forms=[], objects_per_page=25, partial_row='ntds/partials/submission_row.html', base_template='ntds/submissions_base.html', columns=columns, sort_column='pk', sort_ascending=False, current='survey')
def patients(request): from generic.views import generic from generic.sorters import SimpleSorter filter_forms = [SearchPatientsForm, AgeFilterForm] action_forms = [DownloadForm, SendTextForm, SendEmailForm] if not request.user.is_superuser or not request.user.is_staff: country = request.user.get_profile().country title = "Patient Listing For %s" % (" ".join( country.values_list("name", flat=True))) patients = Patient.objects.filter( mission__country__in=country.values("pk")).prefetch_related( "phase1", "phase2", "phase3", "mission") filter_forms.append(SiteFilterForm) else: title = "All Patients" patients = Patient.objects.all().prefetch_related( "phase1", "phase2", "phase3", "mission") filter_forms.append(CountryFilterForm) partial_row = 'mission/partials/patient_row.html' base_template = 'mission/partials/patients_base.html' paginator_template = 'mission/partials/pagination.html' columns = [('Name', True, 'first_name', SimpleSorter()), ('Age', True, 'age', SimpleSorter()), ('Gender', True, 'gender', SimpleSorter()), ('Country', True, 'mission__country__name', SimpleSorter()), ('Mobile', True, 'mobile', SimpleSorter()), ('Email', True, 'email', SimpleSorter()), ('User', True, 'user', SimpleSorter()), ('Actions', False, '', '')] return generic( request, model=Patient, queryset=patients, filter_forms=filter_forms, action_forms=action_forms, objects_per_page=25, partial_row=partial_row, results_title="Patients", title=title, base_template=base_template, paginator_template=paginator_template, paginator_func=paginate, columns=columns, sort_column='pk', show_unfiltered=False, sort_ascending=False, )
from .views import ReporterDetailView urlpatterns = patterns('', url(r'^edtrac/messages/$', login_required(generic), { 'model':Message, 'queryset':messages, 'filter_forms':[FreeSearchTextForm, DistictFilterMessageForm,LastReportingDateFilterForm,PollFilterForm], 'action_forms':[ReplyTextForm], 'objects_per_page':25, 'partial_row' : 'education/partials/messages/message_row.html', 'partial_header':'education/partials/messages/message_partial_header.html', 'base_template':'education/partials/contact_message_base.html', # 'paginator_template' : 'education/partials/pagination.html', 'title' : 'Messages', 'columns':[('Incoming Text', True, 'text', SimpleSorter()), ('Reporter', True, 'connection__contact__name', SimpleSorter(),), ('Number', True, 'connection__identity', SimpleSorter()), ('Poll', True, 'poll_responses.all()[0].poll', SimpleSorter(),), ('School',False,'connection__contact__emisreporter__schools',None,), ('District',True,'connection__contact__reporting_location',SimpleSorter(),), ('Reporting Date', True, 'date', SimpleSorter(),), ], 'sort_column':'date', 'sort_ascending':False, 'management_for': 'messages' }, name="emis-messagelog"), url(r'^edtrac/error_messages/$', login_required(error_messages_as_json), name="error_messages"), url(r'^edtrac/other-messages/$', login_required(generic), { 'model':Message,
class Poll(models.Model): """ Polls represent a simple-question, simple-response communication modality via SMS. They can be thought of as a similar to a single datum in an XForm, although for now the only data types available are yes/no, free-form text, and numeric response. Fairly simple idea, a poll is created, containing a question (the outgoing messages), a list of contacts (those to poll) and an expected *type* of response. The poll can be edited, contact lists modified, etc. via the web (the "user"), until it is eventually *started.* When a poll is started, the outgoing question will be sent to all contacts, and any subsequent messages coming in from the contacts associated with this poll (until they are polled again) will be parsed (or attempted to be parsed) by this poll, and bucketed into a particular category. FIXME: contact groups, if implemented in core or contrib, should be used here, instead of a many-to-many field """ TYPE_TEXT = 't' TYPE_NUMERIC = 'n' TYPE_LOCATION = 'l' TYPE_LOCATION_DISTRICT = 'district' TYPE_REGISTRATION = 'r' RESPONSE_TYPE_ALL = 'a'# all all responses RESPONSE_TYPE_ONE = 'o' # allow only one RESPONSE_TYPE_CHOICES = ( (RESPONSE_TYPE_ALL, 'Allow all'), (RESPONSE_TYPE_ONE, 'Allow one'), ) TYPE_CHOICES = { TYPE_LOCATION: dict( label='Location-based', type=TYPE_LOCATION, db_type=Attribute.TYPE_OBJECT, parser=None, view_template='polls/response_location_view.html', edit_template='polls/response_location_edit.html', report_columns=((('Text', 'text', True, 'message__text', SimpleSorter()), ('Location', 'location', True, 'eav_values__generic_value_id', SimpleSorter()), ('Categories', 'categories', True, 'categories__category__name', SimpleSorter()))), edit_form=LocationResponseForm), TYPE_NUMERIC: dict( label='Numeric Response', type=TYPE_NUMERIC, db_type=Attribute.TYPE_FLOAT, parser=None, view_template='polls/response_numeric_view.html', edit_template='polls/response_numeric_edit.html', report_columns=((('Text', 'text', True, 'message__text', SimpleSorter()), ('Value', 'value', True, 'eav_values__value_float', SimpleSorter()), ('Categories', 'categories', True, 'categories__category__name', SimpleSorter()))), edit_form=NumericResponseForm), TYPE_TEXT: dict( label='Free-form', type=TYPE_TEXT, db_type=Attribute.TYPE_TEXT, parser=None, view_template='polls/response_text_view.html', edit_template='polls/response_text_edit.html', report_columns=(('Text', 'text', True, 'message__text', SimpleSorter()), ('Categories', 'categories', True, 'categories__category__name', SimpleSorter())), edit_form=ResponseForm), TYPE_REGISTRATION: dict( label='Name/registration-based', type=TYPE_REGISTRATION, db_type=Attribute.TYPE_TEXT, parser=None, view_template='polls/response_registration_view.html', edit_template='polls/response_registration_edit.html', report_columns=(('Text', 'text', True, 'message__text', SimpleSorter()), ('Categories', 'categories', True, 'categories__category__name', SimpleSorter())), edit_form=NameResponseForm), } TYPE_CHOICES[TYPE_LOCATION_DISTRICT] = TYPE_CHOICES[TYPE_LOCATION] name = models.CharField(max_length=32, help_text="Human readable name.") question = models.CharField(_("question"), max_length=160) messages = models.ManyToManyField(Message, null=True) contacts = models.ManyToManyField(Contact, related_name='polls') user = models.ForeignKey(User) start_date = models.DateTimeField(null=True) end_date = models.DateTimeField(null=True) type = models.SlugField(max_length=8, null=True, blank=True) default_response = models.CharField(_("default_response"), max_length=160, null=True, blank=True) sites = models.ManyToManyField(Site) objects = models.Manager() on_site = CurrentSiteManager('sites') response_type = models.CharField(max_length=1, choices=RESPONSE_TYPE_CHOICES, default=RESPONSE_TYPE_ALL, null=True, blank=True) class Meta: permissions = ( ("can_poll", "Can send polls"), ("can_edit_poll", "Can edit poll rules, categories, and responses"), ) ordering = ["-end_date"] @classmethod def register_poll_type(cls, field_type, label, parserFunc, \ db_type=TYPE_TEXT, \ view_template=None, \ edit_template=None, \ report_columns=None, \ edit_form=None): """ Used to register a new question type for Polls. You can use this method to build new question types that are available when building Polls. These types may just do custom parsing of the SMS text sent in, then stuff those results in a normal core datatype, or they may lookup and reference completely custom attributes. Arguments are: label: The label used for this field type in the user interface field_type: A slug to identify this field type, must be unique across all field types parser: The function called to turn the raw string into the appropriate type, should take one argument: 'value' the string value submitted. db_type: How the value will be stored in the database, can be one of: TYPE_FLOAT, TYPE_TEXT or TYPE_OBJECT (defaults to TYPE_TEXT) [view_template]: A template that renders an individual row in a table displaying responses [edit_template]: A template that renders an individual row for editing a response [report_columns]: the column labels for a table of responses for a poll of a particular type [edit_form]: A custom edit form for editing responses """ # set the defaults if view_template is None: view_template = 'polls/response_custom_view.html' if edit_template is None: edit_template = 'polls/response_custom_edit.html' if report_columns is None: report_columns = (('Original Text', 'text'), ('Value', 'custom')) Poll.TYPE_CHOICES[field_type] = dict( type=field_type, label=label, db_type=db_type, parser=parserFunc, view_template=view_template, edit_template=edit_template, report_columns=report_columns, edit_form=edit_form) @classmethod @transaction.commit_on_success def create_with_bulk(cls, name, type, question, default_response, contacts, user): if getattr(settings,"BLACKLIST_MODEL",None): app_label,model_name=settings.BLACKLIST_MODEL.rsplit(".") try: blacklists = models.get_model(app_label,model_name)._default_manager.values_list('connection') contacts=contacts.exclude(connection__pk__in=blacklists) except : raise Exception("Your Blacklist Model is Improperly configured") poll = Poll.objects.create(name=name, type=type, question=question, default_response=default_response, user=user) #batch for responses MessageBatch.objects.get_or_create(name=str(poll.pk)) # This is the fastest (pretty much only) was to get contacts and messages M2M into the # DB fast enough at scale cursor = connection.cursor() raw_sql = "insert into poll_poll_contacts (poll_id, contact_id) values %s" % ','.join(\ ["(%d, %d)" % (poll.pk, c.pk) for c in contacts]) cursor.execute(raw_sql) if 'django.contrib.sites' in settings.INSTALLED_APPS: poll.sites.add(Site.objects.get_current()) return poll def add_yesno_categories(self): """ This creates a generic yes/no poll categories for a particular poll """ #langs = self.contacts.values_list('language',flat=True).distinct() langs = dict(settings.LANGUAGES).keys() self.categories.create(name='yes') self.categories.create(name='no') self.categories.create(name='unknown', default=True, error_category=True) # add one rule to yes category per language for l in langs: try: no_words=settings.NO_WORDS.get(l,NO_WORDS) yes_words=settings.YES_WORDS.get(l,YES_WORDS) except AttributeError: no_words=NO_WORDS yes_words=YES_WORDS no_rule_string = '|'.join(no_words) yes_rule_string = '|'.join(yes_words) self.categories.get(name='yes').rules.create( regex=(STARTSWITH_PATTERN_TEMPLATE % yes_rule_string), rule_type=Rule.TYPE_REGEX, rule_string=(STARTSWITH_PATTERN_TEMPLATE % yes_rule_string)) self.categories.get(name='no').rules.create( regex=(STARTSWITH_PATTERN_TEMPLATE % no_rule_string), rule_type=Rule.TYPE_REGEX, rule_string=(STARTSWITH_PATTERN_TEMPLATE % no_rule_string)) def is_yesno_poll(self): return self.categories.count() == 3 and \ self.categories.filter(name='yes').count() and \ self.categories.filter(name='no').count() and \ self.categories.filter(name='unknown').count() @transaction.commit_on_success def start(self): """ This starts the poll: outgoing messages are sent to all the contacts registered with this poll, and the start date is updated accordingly. All incoming messages from these users will be considered as potentially a response to this poll. """ if self.start_date: return contacts = self.contacts localized_messages = {} for language in dict(settings.LANGUAGES).keys(): if language == "en": """default to English for contacts with no language preference""" localized_contacts = contacts.filter(language__in=["en", '']) else: localized_contacts = contacts.filter(language=language) if localized_contacts.exists(): messages = Message.mass_text(gettext_db(field=self.question, language=language), Connection.objects.filter(contact__in=localized_contacts).distinct(), status='Q', batch_status='Q') localized_messages[language] = [messages, localized_contacts] # This is the fastest (pretty much only) was to get messages M2M into the # DB fast enough at scale cursor = connection.cursor() for language in localized_messages.keys(): raw_sql = "insert into poll_poll_messages (poll_id, message_id) values %s" % ','.join(\ ["(%d, %d)" % (self.pk, m.pk) for m in localized_messages.get(language)[0].iterator()]) cursor.execute(raw_sql) self.start_date = datetime.datetime.now() self.save() poll_started.send(sender=self) def end(self): self.end_date = datetime.datetime.now() self.save() def reprocess_responses(self): for rc in ResponseCategory.objects.filter(category__poll=self, is_override=False): rc.delete() for resp in self.responses.all(): resp.has_errors = False for category in self.categories.all(): for rule in category.rules.all(): regex = re.compile(rule.regex, re.IGNORECASE) if resp.eav.poll_text_value: if regex.search(resp.eav.poll_text_value.lower()) and not resp.categories.filter(category=category).count(): if category.error_category: resp.has_errors = True rc = ResponseCategory.objects.create(response=resp, category=category) break if not resp.categories.all().count() and self.categories.filter(default=True).count(): if self.categories.get(default=True).error_category: resp.has_errors = True resp.categories.add(ResponseCategory.objects.create(response=resp, category=self.categories.get(default=True))) resp.save() def process_response(self, message): db_message = None if hasattr(message, 'db_message'): db_message = message.db_message else: db_message=message resp = Response.objects.create(poll=self, message=db_message, contact=db_message.connection.contact, date=db_message.date) outgoing_message = self.default_response if (self.type in [Poll.TYPE_LOCATION, Poll.TYPE_LOCATION_DISTRICT]): location_template = STARTSWITH_PATTERN_TEMPLATE % '[a-zA-Z]*' regex = re.compile(location_template, re.IGNORECASE) if regex.search(message.text): spn = regex.search(message.text).span() location_str = message.text[spn[0]:spn[1]] area = None area_names = Location.objects.all().values_list('name', flat=True) area_names_lower = [ai.lower() for ai in area_names] area_names_matches = difflib.get_close_matches(location_str.lower(), area_names_lower) if area_names_matches: conf = {'name__iexact': area_names_matches[0]} if self.type == Poll.TYPE_LOCATION_DISTRICT: conf['type'] = LocationType.objects.get(name = 'district') area = Location.objects.filter(**conf) if area.count() < 1: resp.has_errors = True else: resp.eav.poll_location_value = area[0] resp.save() else: resp.has_errors = True else: resp.has_errors = True elif (self.type == Poll.TYPE_NUMERIC): try: regex = re.compile(r"(-?\d+(\.\d+)?)") #split the text on number regex. if the msg is of form #'19'or '19 years' or '19years' or 'age19'or 'ugx34.56shs' it returns a list of length 4 msg_parts = regex.split(message.text) if len(msg_parts) == 4 : resp.eav.poll_number_value = float(msg_parts[1]) else: resp.has_errors = True except IndexError: resp.has_errors = True elif ((self.type == Poll.TYPE_TEXT) or (self.type == Poll.TYPE_REGISTRATION)): resp.eav.poll_text_value = message.text if self.categories: for category in self.categories.all(): for rule in category.rules.all(): regex = re.compile(rule.regex, re.IGNORECASE) if regex.search(message.text.lower()): rc = ResponseCategory.objects.create(response=resp, category=category) resp.categories.add(rc) if category.error_category: resp.has_errors = True outgoing_message = category.response break elif self.type in Poll.TYPE_CHOICES: typedef = Poll.TYPE_CHOICES[self.type] try: cleaned_value = typedef['parser'](message.text) if typedef['db_type'] == Attribute.TYPE_TEXT: resp.eav.poll_text_value = cleaned_value elif typedef['db_type'] == Attribute.TYPE_FLOAT or \ typedef['db_type'] == Attribute.TYPE_INT: resp.eav.poll_number_value = cleaned_value elif typedef['db_type'] == Attribute.TYPE_OBJECT: resp.eav.poll_location_value = cleaned_value except ValidationError as e: resp.has_errors = True if getattr(e, 'messages', None): outgoing_message = str(e.messages[0]) else: outgoing_message = None if not resp.categories.all().count() and self.categories.filter(default=True).count(): resp.categories.add(ResponseCategory.objects.create(response=resp, category=self.categories.get(default=True))) if self.categories.get(default=True).error_category: resp.has_errors = True outgoing_message = self.categories.get(default=True).response if (not resp.has_errors or not outgoing_message): for respcategory in resp.categories.order_by('category__priority'): if respcategory.category.response: outgoing_message = respcategory.category.response break resp.save() if not outgoing_message: return (resp, None,) else: if db_message.connection.contact and db_message.connection.contact.language: outgoing_message = gettext_db(language=db_message.connection.contact.language, field=outgoing_message) return (resp, outgoing_message,) def get_numeric_detailed_data(self): return Value.objects.filter(attribute__slug='poll_number_value', entity_ct=ContentType.objects.get_for_model(Response), entity_id__in=self.responses.all()).values_list('value_float').annotate(Count('value_float')).order_by('-value_float') def get_numeric_report_data(self, location=None, for_map=None): if location: q = Value.objects.filter(attribute__slug='poll_number_value', entity_ct=ContentType.objects.get_for_model(Response), entity_id__in=self.responses.all()) q = q.extra(tables=['poll_response', 'rapidsms_contact', 'locations_location', 'locations_location'], where=['poll_response.id = eav_value.entity_id', 'rapidsms_contact.id = poll_response.contact_id', 'locations_location.id = rapidsms_contact.reporting_location_id', 'T7.id in %s' % (str(tuple(location.get_children().values_list('pk', flat=True)))), 'T7.lft <= locations_location.lft', \ 'T7.rght >= locations_location.rght', \ ], select={ 'location_name':'T7.name', 'location_id':'T7.id', 'lft':'T7.lft', 'rght':'T7.rght', }).values('location_name', 'location_id') else: q = Value.objects.filter(attribute__slug='poll_number_value', entity_ct=ContentType.objects.get_for_model(Response), entity_id__in=self.responses.all()).values('entity_ct') q = q.annotate(Sum('value_float'), Count('value_float'), Avg('value_float'), StdDev('value_float'), Max('value_float'), Min('value_float')) return q def responses_by_category(self, location=None, for_map=True): categorized = ResponseCategory.objects.filter(response__poll=self) uncategorized = self.responses.exclude(pk__in=ResponseCategory.objects.filter(response__poll=self).values_list('response', flat=True)) uvalues = ['poll__pk'] if location: if location.get_children().count() == 1: location_where = 'T9.id = %d' % location.get_children()[0].pk ulocation_where = 'T7.id = %d' % location.get_children()[0].pk elif location.get_children().count() == 0: location_where = 'T9.id = %d' % location.pk ulocation_where = 'T7.id = %d' % location.pk else: location_where = 'T9.id in %s' % (str(tuple(location.get_children().values_list('pk', flat=True)))) ulocation_where = 'T7.id in %s' % (str(tuple(location.get_children().values_list('pk', flat=True)))) where_list = [\ 'T9.lft <= locations_location.lft', \ 'T9.rght >= locations_location.rght', \ location_where, \ 'T9.point_id = locations_point.id', ] select = { 'location_name':'T9.name', 'location_id':'T9.id', 'lat':'locations_point.latitude', 'lon':'locations_point.longitude', 'rght':'T9.rght', 'lft':'T9.lft', } tables = ['locations_location', 'locations_point'] if not for_map: where_list = where_list[:3] select.pop('lat') select.pop('lon') tables = tables[:1] categorized = categorized\ .values('response__message__connection__contact__reporting_location__name')\ .extra(tables=tables, \ where=where_list)\ .extra(select=select) uwhere_list = [\ 'T7.lft <= locations_location.lft', \ 'T7.rght >= locations_location.rght', \ ulocation_where, \ 'T7.point_id = locations_point.id', ] uselect = { 'location_name':'T7.name', 'location_id':'T7.id', 'lat':'locations_point.latitude', 'lon':'locations_point.longitude', 'rght':'T7.rght', 'lft':'T7.lft', } uvalues = ['location_name', 'location_id', 'lat', 'lon'] utables = ['locations_location', 'locations_point'] if not for_map: uwhere_list = uwhere_list[:3] uselect.pop('lat') uselect.pop('lon') uvalues = uvalues[:2] utables = utables[:1] uncategorized = uncategorized\ .values('message__connection__contact__reporting_location__name')\ .extra(tables=utables, \ where=uwhere_list)\ .extra(select=uselect) values_list = ['location_name', 'location_id', 'category__name', 'category__color', 'lat', 'lon', ] if not for_map: values_list = values_list[:4] else: values_list = ['category__name', 'category__color'] categorized = categorized.values(*values_list)\ .annotate(value=Count('pk'))\ .order_by('category__name') uncategorized = uncategorized.values(*uvalues).annotate(value=Count('pk')) if location: categorized = categorized.extra(order_by=['location_name']) uncategorized = uncategorized.extra(order_by=['location_name']) if for_map: for d in uncategorized: d['lat'] = '%.5f' % float(d['lat']) d['lon'] = '%.5f' % float(d['lon']) for d in categorized: d['lat'] = '%.5f' % float(d['lat']) d['lon'] = '%.5f' % float(d['lon']) if len(uncategorized): uncategorized = list(uncategorized) for d in uncategorized: d.update({'category__name':'uncategorized', 'category__color':''}) categorized = list(categorized) + uncategorized return categorized def process_uncategorized(self): responses=self.responses.filter(categories__category=None) for resp in responses: resp.has_errors = False for category in self.categories.all(): for rule in category.rules.all(): regex = re.compile(rule.regex, re.IGNORECASE) if resp.eav.poll_text_value: if regex.search(resp.eav.poll_text_value.lower()) and not resp.categories.filter(category=category).count(): if category.error_category: resp.has_errors = True rc = ResponseCategory.objects.create(response=resp, category=category) break if not resp.categories.all().count() and self.categories.filter(default=True).count(): if self.categories.get(default=True).error_category: resp.has_errors = True resp.categories.add(ResponseCategory.objects.create(response=resp, category=self.categories.get(default=True))) resp.save() def __unicode__(self): if self.start_date: sd = self.start_date.date() else: sd = "Not Started" return "%s %s ...(%s)" % (self.name, self.question[0:18], sd)
def ureporters(request): access = get_access(request) download_form = DownloadForm(request.POST or None) if request.POST and request.POST.get('download', None): if download_form.is_valid(): download_form.export(request, request.session['queryset'], 'autoreg_join_date') else: return HttpResponse("Some thing went wrong") columns = [ (_('Identifier'), True, 'connection_pk', SimpleSorter()), (_('Age'), True, 'age', SimpleSorter(),), (_('Gender'), True, 'gender', SimpleSorter(),), (_('Language'), True, 'language', SimpleSorter(),), (_('District'), True, 'district', SimpleSorter(),), (_('Group(s)'), True, 'group', SimpleSorter(),), (_('Questions '), True, 'questions', SimpleSorter(),), (_('Responses '), True, 'responses', SimpleSorter(),), (_('Messages Sent'), True, 'incoming', SimpleSorter(),), (_('caregiver'), True, 'is_caregiver', SimpleSorter(),), (_('join date'), True, 'autoreg_join_date', SimpleSorter(),), (_('quit date'), True, 'quit_date', SimpleSorter(),), ] if request.user.is_staff: columns.insert(1, ('Phone', True, 'mobile', SimpleSorter())) queryset = get_contacts2(request=request) if access is not None: groups = list(access.groups.values_list('name', flat=True)) if len(groups) > 0: qset = Q(group__icontains=groups[0]) if len(groups) > 1: for group in groups[1:]: qset = qset | Q(group__icontains=group) queryset = queryset.filter(qset) return generic(request, model=UreportContact, queryset=queryset, download_form=download_form, results_title= _('uReporters'), filter_forms=[UreporterSearchForm, GenderFilterForm, AgeFilterForm, MultipleDistictFilterForm, FilterGroupsForm], action_forms=[MassTextForm, AssignGroupForm, BlacklistForm, AssignToNewPollForm, RemoveGroupForm, TemplateMessage], objects_per_page=25, partial_row='ureport/partials/contacts/contacts_row.html', base_template='ureport/ureporters_base.html', paginator_template='ureport/partials/new_pagination.html', paginator_func=ureport_paginate, columns=columns, )
def ureporter_profile(request, connection_pk): from script.models import ScriptSession, ScriptResponse, Script connection = get_object_or_404(Connection, pk=connection_pk) session = ScriptSession.objects.filter(connection__pk=connection_pk) messages = Message.objects.filter(connection=connection).order_by('-date') contact = connection.contact if contact: #get the proxy contact = Ureporter.objects.get(pk=connection.contact.pk) reporter_form = EditReporterForm(instance=contact) total_outgoing = messages.filter(direction='O', connection__pk=connection_pk).count() total_incoming = messages.filter(direction='I', connection__pk=connection_pk).count() try: response_rate = contact.responses.values_list( 'poll').distinct().count() * 100 / float( Poll.objects.filter(contacts=contact).distinct().count()) except (ZeroDivisionError, ValueError): response_rate = None # gr_poll = Poll.objects.get(pk=121) gr_poll = Script.objects.get(slug="autoreg_en").steps.get(order=1).poll how_did_u_hear = None if session: try: how_did_u_hear = \ session[0].responses.filter(response__poll=gr_poll)[0].response.message.text except (ScriptResponse.DoesNotExist, IndexError): how_did_u_hear = 'N/A' if request.GET.get('download', None): data = [] data = messages.values_list( 'text', 'direction', 'date', 'connection__contact__reporting_location__name').iterator() headers = ['Message', 'Direction', 'Date', 'District'] return ExcelResponse(data=data, headers=headers) columns = [('Message', True, 'text', SimpleSorter()), ('connection', True, 'connection', SimpleSorter()), ('Date', True, 'date', SimpleSorter()), ('Direction', True, 'direction', SimpleSorter())] # hack hack send the reply message by hacking the sendmessage form if request.method == 'POST': if not request.POST.get('text', None) == u'' and request.POST.get( 'action' ) == u'ureport.forms.ReplyTextForm' and not request.POST.get( 'page_action', None): rep_form = ReplyTextForm(request=request) Message.objects.create(connection=connection, direction='O', status='Q', text=request.POST.get('text')) return generic( request, model=Message, queryset=messages, total_outgoing=total_outgoing, total_incoming=total_incoming, response_rate=response_rate, how_did_u_hear=how_did_u_hear, contact=contact, reporter_form=reporter_form, objects_per_page=20, status_message='Message sent', status_message_type='success', results_title='Message History', selectable=False, partial_row= 'ureport/partials/messages/message_history_row.html', base_template='ureport/message_history_base.html', action_forms=[ReplyTextForm], columns=columns, sort_column='date', sort_ascending=False, ) return generic( request, model=Message, queryset=messages, contact=contact, total_outgoing=total_outgoing, total_incoming=total_incoming, response_rate=response_rate, objects_per_page=20, how_did_u_hear=how_did_u_hear, reporter_form=reporter_form, results_title='Message History', selectable=False, partial_row='ureport/partials/messages/message_history_row.html', base_template='ureport/message_history_base.html', action_forms=[ReplyTextForm], columns=columns, sort_column='date', sort_ascending=False, )
'partial_row': 'ureport/partials/contacts/contact_row2.html', 'base_template': 'ureport/ureporters_base.html', 'paginator_template': 'ureport/partials/pagination.html', 'columns': [( 'Age', False, '', None, ), ( 'Gender', True, 'gender', SimpleSorter(), ), ( 'Language', True, 'language', SimpleSorter(), ), ( 'Location', True, 'reporting_location__name', SimpleSorter(), ), ('Group(s)', True, 'groups__name', SimpleSorter()), ('Total Poll Responses', True, 'responses__count', SimpleSorter()), ('', False, '', None)], }, name="ureport-contact2"),
def ureporters(request): access = get_access(request) print request.method message = '' if request.method == 'POST' and request.FILES: contactsform = ExcelTestUploadForm(request.POST, request.FILES) if contactsform.is_valid() and contactsform.good_file(): new_file = contactsform.cleaned_data fields = [ 'number', 'name', 'province', 'commune', 'colline', 'language', 'county', 'village', 'birthdate', 'group', 'gender', ] message = handle_excel_file_update(new_file['excel_file'], fields) print(message) messages.success(request, message) return HttpResponseRedirect("/reporter") else: return HttpResponse( content='The form is not valid. Resfresh this page') columns = [ ('Identifier', True, 'connection_pk', SimpleSorter()), ('Modile', True, 'mobile', SimpleSorter()), ( 'Age', True, 'age', SimpleSorter(), ), ( 'Gender', True, 'gender', SimpleSorter(), ), ( 'Language', True, 'language', SimpleSorter(), ), ( 'Province', True, 'province', SimpleSorter(), ), ( 'Group(s)', True, 'group', SimpleSorter(), ), ( 'Polls ', True, 'questions', SimpleSorter(), ), ( 'Responses ', True, 'responses', SimpleSorter(), ), ( 'Messages Sent', True, 'incoming', SimpleSorter(), ), # ('caregiver', True, 'is_caregiver', SimpleSorter(),), # ('join date', True, 'autoreg_join_date', SimpleSorter(),), # ('quit date', True, 'quit_date', SimpleSorter(),), ] queryset = get_contacts2(request=request) if access is not None: groups = ",".join(list(access.groups.values_list('name', flat=True))) queryset = queryset.filter(group__icontains=groups) return generic( request, model=UreportContact, queryset=get_contacts2, contactsform=ExcelTestUploadForm, message=message, results_title='uReporters', filter_forms=[ UreporterSearchForm, GenderFilterForm, AgeFilterForm, MultipleDistictFilterForm, FilterGroupsForm, FilterByGroupForm, FilterByLocationForm ], action_forms=[ MassTextForm, AssignGroupForm, BlacklistForm, AssignToNewPollForm, RemoveGroupForm, TemplateMessage, ExportToExcelForm ], objects_per_page=25, base_template='ureport/ureporters_base.html', partial_base='ureport/partials/contacts/partial_base.html', partial_row='ureport/partials/contacts/partial_row.html', paginator_template='ureport/partials/new_pagination.html', paginator_func=ureport_paginate, columns=columns, )
from .forms import FreeSearchTextForm, DistictFilterMessageForm, HandledByForm, ReplyTextForm, FlaggedForm, FlagMessageForm from contact.models import MassText urlpatterns = patterns('', url(r'^contact/index/$', generic, {'model':Contact, 'filter_forms':[FreeSearchForm, FilterGroupsForm], 'action_forms':[MassTextForm], 'objects_per_page':25}), url(r'^contact/add', add_contact), url(r'^contact/new', new_contact), url(r'^contact/messagelog/$', login_required(generic), { 'model':Message, 'queryset':get_messages, 'filter_forms':[FreeSearchTextForm, DistictFilterMessageForm, HandledByForm, FlaggedForm], 'action_forms':[ReplyTextForm, FlagMessageForm], 'objects_per_page':25, 'partial_row':'contact/partials/message_row.html', 'base_template':'contact/messages_base.html', 'columns':[('Text', True, 'text', SimpleSorter()), ('Contact Information', True, 'connection__contact__name', SimpleSorter(),), ('Date', True, 'date', SimpleSorter(),), ('Type', True, 'application', SimpleSorter(),), ('Response', False, 'response', None,), ], 'sort_column':'date', 'sort_ascending':False, }, name="contact-messagelog"), url(r'^contact/massmessages/$', login_required(generic), { 'model':MassText, 'queryset':get_mass_messages, 'objects_per_page':10, 'partial_row':'contact/partials/mass_message_row.html', 'base_template':'contact/mass_messages_base.html', 'columns':[('Message', True, 'text', TupleSorter(0)),
def parse_district_value(value): location_template = STARTSWITH_PATTERN_TEMPLATE % '[a-zA-Z]*' regex = re.compile(location_template) toret = find_closest_match(value, Location.objects.filter(type__name='district')) if not toret: raise ValidationError( "We didn't recognize your district. Please carefully type the name of your district and re-send." ) else: return toret Poll.register_poll_type('district', 'District Response', parse_district_value, db_type=Attribute.TYPE_OBJECT,\ view_template='polls/response_location_view.html', edit_template='polls/response_location_edit.html', report_columns=((('Text', 'text', True, 'message__text', SimpleSorter()), ( 'Location', 'location', True, 'eav_values__generic_value_id', SimpleSorter()), ( 'Categories', 'categories', True, 'categories__category__name', SimpleSorter()))), edit_form=LocationResponseForm) class PolymorphicManager(models.Manager): def get_query_set(self): attrs = [] cls = self.model.__class__ if not hasattr(cls, '_meta'): return QuerySet(self.model, using=self._db) for r in cls._meta.get_all_related_objects(): if not issubclass(r.model, cls) or\ not isinstance(r.field, models.OneToOneField):
}, name='upload-reports'), url('^config/indicators/$', bulk_upload, { \ 'model':Indicator, \ 'model_name':'Indicator', \ 'template':'/static/kit/spreadsheets/indicators_tmpl.xls', \ 'redirect_url':'/', \ }, name='upload-indicators'), url('^users/$', generic, { \ 'model':Contact, \ 'results_title':'Users', \ 'action_forms':[MassTextForm, AssignGroupForm], \ 'base_template':'kit/contacts_base.html', 'partial_row':'kit/partials/contacts/contacts_row.html', \ 'columns':[ \ ('Name', True, 'name', SimpleSorter()), \ ('Number', True, 'connection__identity', SimpleSorter(),), \ ('Location', True, 'reporting_location__name', SimpleSorter(),), \ ('Role(s)', True, 'groups__name', SimpleSorter()), \ ('', False, '', None)], }, name="kit-users"), url(r'^user/(?P<contact_pk>\d+)/edit', edit_reporter), url(r'^user/(?P<contact_pk>\d+)/delete', delete_reporter), url(r'^user/(?P<pk>\d+)/show', generic_row, {'model':Contact, 'partial_row':'kit/partials/contacts/contacts_row.html'}), url('^locations/$', generic, { \ 'model':Location, \ 'results_title':'Locations', \ 'base_template':'kit/locations_base.html', 'partial_row':'kit/partials/locations/locations_row.html', \ 'columns':[ \
location_template = STARTSWITH_PATTERN_TEMPLATE % '[a-zA-Z]*' regex = re.compile(location_template) toret = find_closest_match(value, Location.objects.filter(type__name='district')) if not toret: raise ValidationError( "We didn't recognize your district. Please carefully type the name of your district and re-send." ) else: return toret Poll.register_poll_type('district', 'District Response', parse_district_value, db_type=Attribute.TYPE_OBJECT, \ view_template='polls/response_location_view.html', edit_template='polls/response_location_edit.html', report_columns=((('Text', 'text', True, 'message__text', SimpleSorter()), ( 'Location', 'location', True, 'eav_values__generic_value_id', SimpleSorter()), ( 'Categories', 'categories', True, 'categories__category__name', SimpleSorter()))), edit_form=LocationResponseForm) GROUP_BY_WEEK = 1 GROUP_BY_MONTH = 2 GROUP_BY_DAY = 16 GROUP_BY_QUARTER = 32 months = { 1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr',