def test_xform_with_opening_batch(self): batch = QuestionSet.get(id=self.qset.id) batch.open_for_location(self.ea.locations.first()) response = self._make_odk_request() self.assertEquals(response.status_code, 200) path = '<formID>%s</formID>' % batch.pk self.assertIn(path, response.content)
def __init__(self, indicator, *args, **kwargs): super(IndicatorVariableForm, self).__init__(*args, **kwargs) self.indicator = indicator self.order_fields(['name', 'description', 'test_question', 'validation_test', 'options', 'value', 'min', 'max', 'var_qset']) if self.indicator: self.fields['test_question'].queryset = Question.objects.filter( pk__in=[q.pk for q in indicator.question_set.all_questions]) if self.data.get('test_question', []): options = QuestionOption.objects.filter( question__pk=self.data['test_question']) self.fields['options'].choices = [ (opt.order, opt.text) for opt in options] if self.data.get('var_qset', []): self.fields['test_question'].queryset = Question.objects.filter( id__in=[q.id for q in QuestionSet.get(id=self.data['var_qset']).all_questions])
def _get_group_next_question(question, proposed_next): next_question = proposed_next present_question_group = question.group if hasattr(question, 'group') else None if next_question and AnswerAccessDefinition.is_valid(access.choice_name(), next_question.answer_type) is False: next_question = _get_group_next_question(question, next_question.next_question(reply)) # I hope the next line is not so confusing! # Basically it means treat only if the next question belongs to a different group from the present. # That's if present has a group if hasattr(next_question, 'group') and present_question_group != next_question.group: question_group = next_question.group if question_group: qset = QuestionSet.get(pk=next_question.qset.pk) valid_group = True for condition in question_group.group_conditions.all(): # we are interested in the qset param list with same identifier name as condition.test_question test_question = qset.parameter_list.questions.get(identifier=condition.test_question.identifier) param_value = '' # use answer.as value if session_data[ANSWERS][-1].get(test_question.identifier, None): # last answer entry param_value = session_data[ANSWERS][-1][test_question.identifier] answer_class = Answer.get_class(condition.test_question.answer_type) validator = getattr(answer_class, condition.validation_test, None) if validator is None: raise ValueError('unsupported validator defined on listing question') try: slogger.debug('parm val: %s, params: %s' % (param_value, condition.test_params)) is_valid = validator(param_value, *condition.test_params) except: is_valid = True if is_valid is False: valid_group = False break # fail if any condition fails if valid_group is False: next_question = _get_group_next_question(question, next_question.next_question(reply)) return next_question
def add_logic(request, qset_id, question_id): question = Question.get(id=question_id) batch = QuestionSet.get(id=qset_id) QuestionForm = get_question_form(batch.question_model()) response = None cancel_url = '../' logic_form = LogicForm(question) question_rules_for_batch = {} # question_rules_for_batch[question] = question.rules_for_batch(batch) if request.method == "POST": logic_form = LogicForm(question, data=request.POST) if logic_form.is_valid(): logic_form.save() messages.success(request, 'Logic successfully added.') response = HttpResponseRedirect( reverse('qset_questions_page', args=(batch.pk, ))) breadcrumbs = Question.edit_breadcrumbs(qset=batch) if breadcrumbs: request.breadcrumbs(breadcrumbs) cancel_url = breadcrumbs[-1][1] context = { 'logic_form': logic_form, 'button_label': 'Save', 'question': question, 'USSD_MAX_CHARS': settings.USSD_MAX_CHARS, 'rules_for_batch': question_rules_for_batch, 'questionform': QuestionForm(batch, parent_question=question), 'modal_action': reverse('add_qset_subquestion_page', args=(batch.pk, )), 'class': 'question-form', 'batch_id': qset_id, 'batch': batch, 'cancel_url': cancel_url } return response or render(request, "set_questions/logic.html", context)
def edit(request, question_id): question = Question.get(id=question_id) batch = QuestionSet.get(pk=question.qset.pk) response, context = _render_question_view( request, batch, instance=question) context['page_title '] = 'Edit Question' return response or render(request, 'set_questions/new.html', context)
def _remove(request, question_id): question = Question.get(pk=question_id) batch_id = question.qset.id batch = QuestionSet.get(pk=batch_id) redirect_url = reverse('qset_questions_page', args=(batch_id, )) if question.total_answers() > 0: messages.error( request, "Cannot delete question that has been answered at least once.") else: _kill_zombies(batch.zombie_questions()) if question: success_message = "Question successfully deleted." # % ("Sub question" if question.subquestion else "Question")) messages.success(request, success_message) next_question = batch.next_inline(question) previous_inline = question.connecting_flows.filter(validation__isnull=True) if previous_inline.exists() and next_question: QuestionFlow.objects.create( question=previous_inline[0].question, next_question=next_question) elif next_question: # need to delete the previous flow for the next question batch.start_question = next_question batch.save() question.connecting_flows.all().delete() question.flows.all().delete() question.delete() return HttpResponseRedirect(redirect_url)
def insert(request, prev_quest_id): prev_question = Question.get(pk=prev_quest_id) batch = QuestionSet.get(pk=prev_question.qset.pk) response, context = _render_question_view( request, batch, prev_question=prev_question) context['prev_question'] = prev_question return response or render(request, 'set_questions/new.html', context)
def _remove(request, question_id): question = Question.get(pk=question_id) batch_id = question.qset.id batch = QuestionSet.get(pk=batch_id) redirect_url = reverse('qset_questions_page', args=(batch_id, )) if question.total_answers() > 0: messages.error( request, "Cannot delete question that has been answered at least once.") else: _kill_zombies(batch.zombie_questions()) if question: success_message = "Question successfully deleted." # % ("Sub question" if question.subquestion else "Question")) messages.success(request, success_message) next_question = batch.next_inline(question) previous_inline = question.connecting_flows.filter( validation__isnull=True) if previous_inline.exists() and next_question: QuestionFlow.objects.create(question=previous_inline[0].question, next_question=next_question) elif next_question: # need to delete the previous flow for the next question batch.start_question = next_question batch.save() question.connecting_flows.all().delete() question.flows.all().delete() question.delete() return HttpResponseRedirect(redirect_url)
def clean_identifier(self): identifier = self.cleaned_data['identifier'] pattern = '^[a-zA-Z][0-9a-zA-Z_]+$' if re.match(pattern, identifier) is None: raise ValidationError( 'Identifier must start with a letter, and must contain alphanumeric values or _') if Question.objects.filter( identifier__iexact=identifier, qset__pk=self.qset.pk).exists(): if self.instance and self.instance.identifier == identifier: pass else: raise ValidationError( '%s already in use for this %s' % (identifier, model_class.type_name())) # if this is a batch question also check if there are parameter # questions with this name qset = QuestionSet.get(id=self.qset.pk) if hasattr( qset, 'parameter_list') and qset.parameter_list and qset.parameter_list.parameters.filter( identifier__iexact=identifier).exists(): raise ValidationError( '%s is already in captured as a group parameter for this %s' % (identifier, qset.verbose_name())) # for sampled surveys, check if this is already implemented in listing if hasattr(qset, 'survey') and qset.survey.listing_form and qset.survey.listing_form.questions.filter( identifier__iexact=identifier).exists(): raise ValidationError( '%s is already in captured as a listing question for this %s' % (identifier, qset.verbose_name())) return self.cleaned_data['identifier']
def identifiers(request): id = request.GET.get('id', None) last_question_id = request.GET.get('q_id', None) if last_question_id is None: json_dump = json.dumps( list( Question.objects.filter( qset__id=id).values_list( 'identifier', flat=True))) else: # return questions before last question qset = QuestionSet.get(pk=id) identifiers = set() for question in qset.flow_questions: if int(question.id) == int(last_question_id): break identifiers.add(question.identifier) # try: # qset = Batch.get(pk=qset.pk) # if hasattr(qset, 'parameter_list'): # identifiers.union(qset.parameter_list.questions.values_list\ #('identifier', flat=True)) # except Batch.DoesNotExist: # pass json_dump = json.dumps(list(identifiers)) return HttpResponse(json_dump, content_type='application/json')
def manage_loop(request, question_id): question = Question.get(id=question_id) batch = QuestionSet.get(pk=question.qset.pk) cancel_url = '../' existing_loop = getattr(question, 'loop_started', None) looping_form = LoopingForm(question, instance=existing_loop) if request.method == "POST": looping_form = LoopingForm(question, instance=existing_loop, data=request.POST) if looping_form.is_valid(): looping_form.save() messages.success(request, 'Loop Logic successfully added.') return HttpResponseRedirect( reverse('qset_questions_page', args=(batch.pk, ))) breadcrumbs = Question.edit_breadcrumbs(qset=batch) if breadcrumbs: request.breadcrumbs(breadcrumbs) cancel_url = breadcrumbs[-1][1] context = { 'loop_form': looping_form, 'button_label': 'Save', 'question': question, 'cancel_url': cancel_url } return render(request, "set_questions/loop.html", context)
def manage_loop(request, question_id): question = Question.get(id=question_id) batch = QuestionSet.get(pk=question.qset.pk) cancel_url = '../' existing_loop = getattr(question, 'loop_started', None) looping_form = LoopingForm(question, instance=existing_loop) if request.method == "POST": looping_form = LoopingForm( question, instance=existing_loop, data=request.POST) if looping_form.is_valid(): looping_form.save() messages.success(request, 'Loop Logic successfully added.') return HttpResponseRedirect( reverse( 'qset_questions_page', args=( batch.pk, ))) breadcrumbs = Question.edit_breadcrumbs(qset=batch) if breadcrumbs: request.breadcrumbs(breadcrumbs) cancel_url = breadcrumbs[-1][1] context = { 'loop_form': looping_form, 'button_label': 'Save', 'question': question, 'cancel_url': cancel_url} return render(request, "set_questions/loop.html", context)
def index(request, qset_id): # now I'm gonna call question set a batch of questions.\ #If there's time, I'll rename them properly # So don't get confused :) try: batch = QuestionSet.get(pk=qset_id) except QuestionSet.DoesNotExist: raise Http404("No QuestionSet Model matches the given query.") questions = batch.questions_inline() request_data = request.GET if request.method == 'GET' else request.POST question_filter_form = QuestionFilterForm(data=request_data, qset=batch) search_fields = ['identifier', 'text', ] qset_questions = batch.questions.all() if 'q' in request_data: questions = get_filterset(qset_questions, request_data['q'], search_fields) if 'question_types' in request_data: relevant_ids = list(question_filter_form.filter( qset_questions).values_list('id', flat=True)) questions = [q for q in questions if q.id in relevant_ids] # now maintain same inline other exclusing questions in breadcrumbs = Question.index_breadcrumbs(qset=batch) if breadcrumbs: request.breadcrumbs(breadcrumbs) context = {'questions': questions, 'request': request, 'batch': batch, 'question_filter_form': question_filter_form, 'placeholder': 'identifier, text', 'template_file': 'interviews/answer.html', 'is_preview': True # caution atleast on ODK access # at least on access must exist } return render(request, 'set_questions/index.html', context)
def identifiers(request): id = request.GET.get('id', None) last_question_id = request.GET.get('q_id', None) if last_question_id is None: json_dump = json.dumps( list( Question.objects.filter(qset__id=id).values_list('identifier', flat=True))) else: # return questions before last question qset = QuestionSet.get(pk=id) identifiers = set() for question in qset.flow_questions: if int(question.id) == int(last_question_id): break identifiers.add(question.identifier) # try: # qset = Batch.get(pk=qset.pk) # if hasattr(qset, 'parameter_list'): # identifiers.union(qset.parameter_list.questions.values_list\ #('identifier', flat=True)) # except Batch.DoesNotExist: # pass json_dump = json.dumps(list(identifiers)) return HttpResponse(json_dump, content_type='application/json')
def __init__(self, qset, *args, **kwargs): super(QuestionSetResultsFilterForm, self).__init__(*args, **kwargs) self.qset = QuestionSet.get(pk=qset.pk) if hasattr(self.qset, 'survey') is False: self.fields['survey'] = forms.ModelChoiceField( queryset=Survey.objects.filter(listing_form__pk=self.qset.pk), required=False, empty_label='Choose Survey')
def edit(request, question_id): question = Question.get(id=question_id) batch = QuestionSet.get(pk=question.qset.pk) response, context = _render_question_view(request, batch, instance=question) context['page_title '] = 'Edit Question' return response or render(request, 'set_questions/new.html', context)
def insert(request, prev_quest_id): prev_question = Question.get(pk=prev_quest_id) batch = QuestionSet.get(pk=prev_question.qset.pk) response, context = _render_question_view(request, batch, prev_question=prev_question) context['prev_question'] = prev_question return response or render(request, 'set_questions/new.html', context)
def export_batch_questions(request, qset_id): batch = QuestionSet.get(pk=qset_id) filename = '%s_questions' % batch.name formatted_responses = get_question_as_dump(batch.flow_questions) response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment;\ filename="%s.csv"' % filename response.write("\r\n".join(formatted_responses)) return response
def _save_answers(self, request, session_data, navigation_interview): answers = session_data[ANSWERS] reference_interview = session_data.get(REF_INTERVIEW, None) qset = QuestionSet.get(pk=navigation_interview.question_set.pk) question_map = dict([(q.identifier, q) for q in qset.all_questions]) survey = navigation_interview.survey ea = navigation_interview.ea Interview.save_answers(qset, survey, ea, navigation_interview.interview_channel, question_map, answers, reference_interview=reference_interview)
def _save_subquestion(request, batch_id, instance=None): # possible subquestions are questions not bound to any interviewer yet batch = QuestionSet.get(pk=batch_id) QuestionForm = get_question_form(batch.question_model()) questionform = QuestionForm(batch, instance=instance) if request.method == 'POST': questionform = QuestionForm( batch, data=request.POST, instance=instance) if questionform.is_valid(): if instance: zombify = False else: zombify = True question = questionform.save(zombie=zombify) if request.is_ajax(): return HttpResponse( json.dumps( { 'id': question.pk, 'text': question.text, 'identifier': question.identifier}), content_type='application/json') messages.info(request, 'Sub Question saved') if instance: heading = 'Edit Subquestion' else: heading = 'New Subquestion' context = { 'questionform': questionform, 'button_label': 'Create', 'id': 'add-sub_question-form', 'USSD_MAX_CHARS': settings.USSD_MAX_CHARS, 'save_url': reverse( '%s_home' % batch.resolve_tag()), 'cancel_url': reverse( 'qset_questions_page', args=( batch.pk, )), 'class': 'question-form', 'heading': heading} breadcrumbs = Question.edit_breadcrumbs(qset=batch) if breadcrumbs: request.breadcrumbs(breadcrumbs) template_name = 'set_questions/new.html' if request.is_ajax(): template_name = 'set_questions/_add_question.html' return render(request, template_name, context) else: return HttpResponseRedirect( reverse( 'qset_questions_page', args=( batch.pk, )))
def question_validators(request): values = {} if request.GET.get('id'): for question in QuestionSet.get( id=request.GET.get('id')).all_questions: values['%s' % question.id] = [ validator for validator in question.validator_names()] elif request.GET.get('ques_id'): values = Question.get(id=request.GET.get('ques_id')).validator_names() return HttpResponse(json.dumps(values), content_type='application/json')
def handle_request(request, qset_id): qset = QuestionSet.get(id=qset_id) request_data = request.GET if request.method == 'GET' else request.POST mock_access = MockAccess(request, qset) if 'uid' in request_data: mock_access.id = str(request_data['uid']) handler = SimulatorView( mock_access, action_url=reverse('test_qset_flow', args=(qset_id, ))) return handler.handle_session(request)
def handle_request(request, qset_id): qset = QuestionSet.get(id=qset_id) request_data = request.GET if request.method == 'GET' else request.POST mock_access = MockAccess(request, qset) if 'uid' in request_data: mock_access.id = str(request_data['uid']) handler = SimulatorView(mock_access, action_url=reverse('test_qset_flow', args=(qset_id, ))) return handler.handle_session(request)
def question_validators(request): values = {} if request.GET.get('id'): for question in QuestionSet.get( id=request.GET.get('id')).all_questions: values['%s' % question.id] = [ validator for validator in question.validator_names() ] elif request.GET.get('ques_id'): values = Question.get(id=request.GET.get('ques_id')).validator_names() return HttpResponse(json.dumps(values), content_type='application/json')
def delete(request, question_id, batch_id): # todo: Should remove question_id from this parameters :( qset = QuestionSet.get(pk=batch_id) view = QuestionSetView(qset.__class__) if qset.__class__ == Batch: survey = qset.survey view.delete(request, qset) return HttpResponseRedirect( reverse('batch_index_page', args=(survey.id, ))) else: return view.delete(request, qset)
def list_questions(request): if request.GET.get('id'): values = [{ 'id': q.id, 'identifier': q.identifier, 'text': q.text } for q in QuestionSet.get(id=request.GET.get('id')).all_questions] else: values = list(Question.objects.all().values('id', 'identifier', 'text')) return HttpResponse(json.dumps(list(values)), content_type='application/json')
def _is_relevant_by_group(qset): qset = QuestionSet.get(pk=qset.pk) relevant_new = [] for condition in question_group.group_conditions.all(): test_question = qset.parameter_list.questions.get(identifier=condition.test_question.identifier) answer_class = Answer.get_class(condition.test_question.answer_type) relevant_new.append(answer_class.print_odk_validation(get_group_question_path(qset, test_question), condition.validation_test, *condition.test_params)) relevance_builder = ['false()', ] if relevant_new: relevance_builder.append('(%s)' % ' and '.join(relevant_new)) return ' and (%s)' % ' or '.join(relevance_builder)
def question_options(request): values = {} if request.GET.get('id'): for question in QuestionSet.get( id=request.GET.get('id')).all_questions: values['%s' % question.id] = dict([ (opt.order, opt.text) for opt in question.options.all() ]) elif request.GET.get('ques_id'): values = dict( Question.get(id=request.GET.get('ques_id')).options.values_list( 'order', 'text')) return HttpResponse(json.dumps(values), content_type='application/json')
def _get_group_next_question(question, proposed_next): next_question = proposed_next present_question_group = question.group if hasattr( question, 'group') else None if next_question and AnswerAccessDefinition.is_valid( access.choice_name(), next_question.answer_type) is False: next_question = _get_group_next_question( question, next_question.next_question(reply)) # I hope the next line is not so confusing! # Basically it means treat only if the next question belongs to a different group from the present. # That's if present has a group if hasattr( next_question, 'group') and present_question_group != next_question.group: question_group = next_question.group if question_group: qset = QuestionSet.get(pk=next_question.qset.pk) valid_group = True for condition in question_group.group_conditions.all(): # we are interested in the qset param list with same identifier name as condition.test_question test_question = qset.parameter_list.questions.get( identifier=condition.test_question.identifier) param_value = '' # use answer.as value if session_data[ANSWERS][-1].get( test_question.identifier, None): # last answer entry param_value = session_data[ANSWERS][-1][ test_question.identifier] answer_class = Answer.get_class( condition.test_question.answer_type) validator = getattr(answer_class, condition.validation_test, None) if validator is None: raise ValueError( 'unsupported validator defined on listing question' ) try: slogger.debug('parm val: %s, params: %s' % (param_value, condition.test_params)) is_valid = validator(param_value, *condition.test_params) except: is_valid = True if is_valid is False: valid_group = False break # fail if any condition fails if valid_group is False: next_question = _get_group_next_question( question, next_question.next_question(reply)) return next_question
def question_options(request): values = {} if request.GET.get('id'): for question in QuestionSet.get( id=request.GET.get('id')).all_questions: values['%s' % question.id] = dict( [(opt.order, opt.text) for opt in question.options.all()]) elif request.GET.get('ques_id'): values = dict( Question.get( id=request.GET.get('ques_id')).options.values_list( 'order', 'text')) return HttpResponse(json.dumps(values), content_type='application/json')
def _save_subquestion(request, batch_id, instance=None): # possible subquestions are questions not bound to any interviewer yet batch = QuestionSet.get(pk=batch_id) QuestionForm = get_question_form(batch.question_model()) questionform = QuestionForm(batch, instance=instance) if request.method == 'POST': questionform = QuestionForm(batch, data=request.POST, instance=instance) if questionform.is_valid(): if instance: zombify = False else: zombify = True question = questionform.save(zombie=zombify) if request.is_ajax(): return HttpResponse(json.dumps({ 'id': question.pk, 'text': question.text, 'identifier': question.identifier }), content_type='application/json') messages.info(request, 'Sub Question saved') if instance: heading = 'Edit Subquestion' else: heading = 'New Subquestion' context = { 'questionform': questionform, 'button_label': 'Create', 'id': 'add-sub_question-form', 'USSD_MAX_CHARS': settings.USSD_MAX_CHARS, 'save_url': reverse('%s_home' % batch.resolve_tag()), 'cancel_url': reverse('qset_questions_page', args=(batch.pk, )), 'class': 'question-form', 'heading': heading } breadcrumbs = Question.edit_breadcrumbs(qset=batch) if breadcrumbs: request.breadcrumbs(breadcrumbs) template_name = 'set_questions/new.html' if request.is_ajax(): template_name = 'set_questions/_add_question.html' return render(request, template_name, context) else: return HttpResponseRedirect( reverse('qset_questions_page', args=(batch.pk, )))
def list_questions(request): if request.GET.get('id'): values = [{ 'id': q.id, 'identifier': q.identifier, 'text': q.text} for q in QuestionSet.get(id=request.GET.get('id')).all_questions] else: values = list( Question.objects.all().values( 'id', 'identifier', 'text')) return HttpResponse( json.dumps( list(values)), content_type='application/json')
def view_data(request, qset_id): qset = QuestionSet.get(pk=qset_id) request.breadcrumbs(qset.edit_breadcrumbs(qset=qset)) disabled_fields = [] request.GET = request.GET.copy() request.GET['question_set'] = qset_id disabled_fields.append('question_set') if hasattr(qset, 'survey'): request.GET['survey'] = qset.survey.id disabled_fields.append('survey') title = 'View Data' return _view_qset_data(request, qset.__class__, Interview.objects.filter(question_set__id=qset_id), title, disabled_fields=disabled_fields)
def identifiers(request): id = request.GET.get('id', None) last_question_id = request.GET.get('q_id', None) if last_question_id is None: json_dump = json.dumps( list( Question.objects.filter(qset__id=id).values_list('identifier', flat=True))) else: # return questions before last question qset = QuestionSet.get(pk=id) identifiers = set() for question in qset.flow_questions: if int(question.id) == int(last_question_id): break identifiers.add(question.identifier) json_dump = json.dumps(list(identifiers)) return HttpResponse(json_dump, content_type='application/json')
def view_data(request, qset_id): qset = QuestionSet.get(pk=qset_id) request.breadcrumbs(qset.edit_breadcrumbs(qset=qset)) disabled_fields = [] request.GET = request.GET.copy() request.GET['question_set'] = qset_id disabled_fields.append('question_set') if hasattr(qset, 'survey'): request.GET['survey'] = qset.survey.id disabled_fields.append('survey') title = 'View Data' return _view_qset_data( request, qset.__class__, Interview.objects.filter( question_set__id=qset_id), title, disabled_fields=disabled_fields)
def update_orders(request, qset_id): batch = QuestionSet.get(id=qset_id) new_orders = request.POST.getlist('order_information', None) if len(new_orders) > 0: # wipe off present inline flows inlines = batch.questions_inline() if inlines: start_question = inlines[0] question = start_question while len(inlines) > 0: question = inlines.pop(0) QuestionFlow.objects.filter(question=question).delete() order_details = [] map(lambda order: order_details.append(order.split('-')), new_orders) order_details = sorted( order_details, key=lambda detail: int(detail[0])) # recreate the flows questions = batch.questions.all() if questions: # so all questions can be fetched once and cached question_id = order_details.pop(0)[1] start_question = questions.get(pk=question_id) for order, next_question_id in order_details: QuestionFlow.objects.create( question=questions.get( pk=question_id), next_question=questions.get( pk=next_question_id)) question_id = next_question_id batch.start_question = start_question batch.save() # better to clear all loops tied to this qset for now QuestionLoop.objects.filter(loop_starter__qset__pk=batch.pk).delete() success_message = "Question orders successfully updated for batch:\ %s." % batch.name.capitalize() messages.success(request, success_message) else: messages.error(request, 'No questions orders were updated.') return HttpResponseRedirect( reverse( 'qset_questions_page', args=( batch.pk, )))
def index(request, qset_id): # now I'm gonna call question set a batch of questions.\ #If there's time, I'll rename them properly # So don't get confused :) try: batch = QuestionSet.get(pk=qset_id) except QuestionSet.DoesNotExist: raise Http404("No QuestionSet Model matches the given query.") questions = batch.questions_inline() request_data = request.GET if request.method == 'GET' else request.POST question_filter_form = QuestionFilterForm(data=request_data, qset=batch) search_fields = [ 'identifier', 'text', ] qset_questions = batch.questions.all() if 'q' in request_data: questions = get_filterset(qset_questions, request_data['q'], search_fields) if 'question_types' in request_data: relevant_ids = list( question_filter_form.filter(qset_questions).values_list('id', flat=True)) questions = [q for q in questions if q.id in relevant_ids] # now maintain same inline other exclusing questions in breadcrumbs = Question.index_breadcrumbs(qset=batch) if breadcrumbs: request.breadcrumbs(breadcrumbs) context = { 'questions': questions, 'request': request, 'batch': batch, 'question_filter_form': question_filter_form, 'placeholder': 'identifier, text', 'template_file': 'interviews/answer.html', 'is_preview': True # caution atleast on ODK access # at least on access must exist } return render(request, 'set_questions/index.html', context)
def update_orders(request, qset_id): batch = QuestionSet.get(id=qset_id) new_orders = request.POST.getlist('order_information', None) if len(new_orders) > 0: # wipe off present inline flows inlines = batch.questions_inline() if inlines: start_question = inlines[0] question = start_question while len(inlines) > 0: question = inlines.pop(0) QuestionFlow.objects.filter(question=question).delete() order_details = [] map(lambda order: order_details.append(order.split('-')), new_orders) order_details = sorted(order_details, key=lambda detail: int(detail[0])) # recreate the flows questions = batch.questions.all() if questions: # so all questions can be fetched once and cached question_id = order_details.pop(0)[1] start_question = questions.get(pk=question_id) for order, next_question_id in order_details: QuestionFlow.objects.create( question=questions.get(pk=question_id), next_question=questions.get(pk=next_question_id)) question_id = next_question_id batch.start_question = start_question batch.save() # better to clear all loops tied to this qset for now QuestionLoop.objects.filter( loop_starter__qset__pk=batch.pk).delete() success_message = "Question orders successfully updated for batch:\ %s." % batch.name.capitalize() messages.success(request, success_message) else: messages.error(request, 'No questions orders were updated.') return HttpResponseRedirect( reverse('qset_questions_page', args=(batch.pk, )))
def download_data(request, qset_id): qset = QuestionSet.get(pk=qset_id) params = request.GET if request.method == 'GET' else request.POST survey_filter = QuestionSetResultsFilterForm(qset, data=params) locations_filter = LocationsFilterForm(data=request.GET, include_ea=True) interviews = survey_filter.get_interviews() if locations_filter.is_valid(): interviews = interviews.filter( ea__in=locations_filter.get_enumerations()).order_by('created') last_selected_loc = locations_filter.last_location_selected download_service = ResultsDownloadService(qset, interviews=interviews) file_name = '%s%s' % ('%s-%s-' % (last_selected_loc.type.name, last_selected_loc.name) if last_selected_loc else '', qset.name) reports_df = download_service.generate_interview_reports() response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment;\ filename="%s.csv"' % file_name reports_df.to_csv(response, date_format='%Y-%m-%d %H:%M:%S', encoding='utf-8') # exclude interview id return response
def add_logic(request, qset_id, question_id): question = Question.get(id=question_id) batch = QuestionSet.get(id=qset_id) QuestionForm = get_question_form(batch.question_model()) response = None cancel_url = '../' logic_form = LogicForm(question) question_rules_for_batch = {} # question_rules_for_batch[question] = question.rules_for_batch(batch) if request.method == "POST": logic_form = LogicForm(question, data=request.POST) if logic_form.is_valid(): logic_form.save() messages.success(request, 'Logic successfully added.') response = HttpResponseRedirect( reverse('qset_questions_page', args=(batch.pk, ))) breadcrumbs = Question.edit_breadcrumbs(qset=batch) if breadcrumbs: request.breadcrumbs(breadcrumbs) cancel_url = breadcrumbs[-1][1] context = { 'logic_form': logic_form, 'button_label': 'Save', 'question': question, 'USSD_MAX_CHARS': settings.USSD_MAX_CHARS, 'rules_for_batch': question_rules_for_batch, 'questionform': QuestionForm( batch, parent_question=question), 'modal_action': reverse( 'add_qset_subquestion_page', args=( batch.pk, )), 'class': 'question-form', 'batch_id': qset_id, 'batch': batch, 'cancel_url': cancel_url} return response or render(request, "set_questions/logic.html", context)
def clean_group(self): group = self.cleaned_data['group'] if group: qset = QuestionSet.get(id=self.qset.pk) identifiers = group.parameter_questions().values_list('identifier', flat=True) existing_identifiers = Question.objects.filter(identifier__in=identifiers, qset__pk=self.qset.pk).values_list('identifier', flat=True) if existing_identifiers.exists(): raise ValidationError( '%s already exist in this %s. ' 'Consider creating a question with modified identifier name and using skip logic in your %s' % (','.join(existing_identifiers), qset.verbose_name(), qset.verbose_name())) if hasattr(qset, 'survey') and qset.survey.listing_form: existing_identifiers = qset.survey.listing_form.questions.filter(identifier__in=identifiers ).values_list('identifier', flat=True) if existing_identifiers.exists(): raise ValidationError( '%s already exist as a listing question for this %s. ' 'Consider creating a question with modified identifier name and using skip logic in your %s' % (','.join(existing_identifiers), qset.verbose_name(), qset.verbose_name())) return group
def handle(self, *args, **kwargs): """Basically loads each line of the csv as9 responses to the question set each row is seen as a seperate interview.9 first field would be the ea ID, subsequent fields would be the answers9 :param args: :param kwargs: :return: """ self.stdout.write('Starting...') delimiter = kwargs.get('delim', ',') df = pd.read_csv(args[0], delimiter=delimiter) interviewer = Interviewer.get(pk=args[1]) survey = Survey.get(pk=args[2]) qset = QuestionSet.get(pk=int(args[3])) odk_access = interviewer.odk_access[0] all_questions = qset.all_questions eas = {} #>with transaction.atomic(): df.apply(save_interview, axis=1, args=(interviewer, odk_access, survey, qset, all_questions, eas)) self.stdout.write('Successfully imported!')
def __init__(self, indicator, *args, **kwargs): super(IndicatorVariableForm, self).__init__(*args, **kwargs) self.indicator = indicator self.order_fields([ 'name', 'description', 'test_question', 'validation_test', 'options', 'value', 'min', 'max', 'var_qset' ]) if self.indicator: self.fields['test_question'].queryset = Question.objects.filter( pk__in=[q.pk for q in indicator.question_set.all_questions]) if self.data.get('test_question', []): options = QuestionOption.objects.filter( question__pk=self.data['test_question']) self.fields['options'].choices = [(opt.order, opt.text) for opt in options] if self.data.get('var_qset', []): self.fields['test_question'].queryset = Question.objects.filter( id__in=[ q.id for q in QuestionSet.get( id=self.data['var_qset']).all_questions ])
def clean_group(self): group = self.cleaned_data['group'] if group: qset = QuestionSet.get(id=self.qset.pk) identifiers = group.parameter_questions().values_list('identifier', flat=True) existing_identifiers = Question.objects.filter(identifier__in=identifiers, qset__pk=self.qset.pk).values_list('identifier', flat=True) if existing_identifiers.exists(): raise ValidationError( '%s already exist in this %s. ' 'Consider creating a question with modified identifier name and using skip logic in your %s' % (','.join(existing_identifiers), qset.verbose_name(), qset.verbose_name())) if hasattr(qset, 'survey') and qset.survey.listing_form: existing_identifiers = qset.survey.listing_form.questions.filter(identifier__in=identifiers ).values_list('identifier', flat=True) if existing_identifiers.exists(): raise ValidationError( '%s already exist as a listing question for this %s. ' 'Consider creating a question with modified identifier name ' 'and using skip logic in your %s' % (','.join(existing_identifiers), qset.verbose_name(), qset.verbose_name())) return group
def download_data(request, qset_id): qset = QuestionSet.get(pk=qset_id) params = request.GET if request.method == 'GET' else request.POST survey_filter = QuestionSetResultsFilterForm(qset, data=params) locations_filter = LocationsFilterForm(data=request.GET, include_ea=True) interviews = survey_filter.get_interviews() if locations_filter.is_valid(): interviews = interviews.filter( ea__in=locations_filter.get_enumerations()).order_by('created') last_selected_loc = locations_filter.last_location_selected download_service = ResultsDownloadService(qset, interviews=interviews) file_name = '%s%s' % ('%s-%s-' % ( last_selected_loc.type.name, last_selected_loc.name) if last_selected_loc else '', qset.name) reports_df = download_service.generate_interview_reports() response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment;\ filename="%s.csv"' % file_name reports_df.to_csv( response, date_format='%Y-%m-%d %H:%M:%S', encoding='utf-8') # exclude interview id return response
def get_questions_for_batch(request, batch_id, question_id): batch = QuestionSet.get(id=batch_id) questions = batch.questions_inline() questions = [q for q in questions if int(q.pk) is not int(question_id)] return _create_question_hash_response(questions)
def __init__(self, request, qset, access_type=ODKAccess.choice_name()): self.id = 'test: %s, %s' % (request.user.username, qset.id) self.question_set = QuestionSet.get(id=qset.id) self.user_identifier = self.id self.access_type = access_type
def new(request, qset_id): batch = QuestionSet.get(pk=qset_id) # can be listng or actual batch response, context = _render_question_view(request, batch) context['page_title '] = 'Add Question' return response or render(request, 'set_questions/new.html', context)
def clone_qset(request, qset_id): qset = QuestionSet.get(pk=qset_id) qset.deep_clone() messages.info(request, 'Successfully cloned %s' % qset.name) return HttpResponseRedirect(reverse('%s_home' % qset.resolve_tag()))
def _get_qset(survey_tree): pk = _get_nodes(FORM_ID_PATH, tree=survey_tree)[0] return QuestionSet.get(pk=pk)
def __init__(self, qset, *args, **kwargs): super(QuestionSetResultsFilterForm, self).__init__(*args, **kwargs) self.qset = QuestionSet.get(pk=qset.pk) if hasattr(self.qset, 'survey') is False: self.fields['survey'] = forms.ModelChoiceField(queryset=Survey.objects.filter( listing_form__pk=self.qset.pk), required=False, empty_label='Choose Survey')
def assign(request, qset_id): batch = QuestionSet.get(id=qset_id) if batch.interviews.count(): error_message = "Questions cannot be assigned \ interviews has already been conducted: %s." % \ batch.name.capitalize() messages.error(request, error_message) return HttpResponseRedirect( reverse('qset_questions_page', args=(batch.pk, ))) if request.method == 'POST': data = dict(request.POST) last_question = batch.last_question_inline() lib_questions = QuestionTemplate.objects.filter( identifier__in=data.get('identifier', '')) if lib_questions: for lib_question in lib_questions: question = Question.objects.create( identifier=lib_question.identifier, text=lib_question.text, answer_type=lib_question.answer_type, qset=batch, ) # assign the options for option in lib_question.options.all(): QuestionOption.objects.create(question=question, text=option.text, order=option.order) if last_question: QuestionFlow.objects.create(question=last_question, next_question=question) else: batch.start_question = question batch.save() last_question = question #batch_questions_form = BatchQuestionsForm(batch=batch,\ #\data=request.POST, instance=batch) success_message = "Questions successfully assigned to %s: %s." % ( batch.verbose_name(), batch.name.capitalize()) messages.success(request, success_message) return HttpResponseRedirect( reverse('qset_questions_page', args=(batch.pk, ))) used_identifiers = [ question.identifier for question in batch.questions.all() ] library_questions = QuestionTemplate.objects.exclude( identifier__in=used_identifiers).order_by('identifier') question_filter_form = QuestionFilterForm() # library_questions = question_filter_form.filter(library_questions) breadcrumbs = Question.edit_breadcrumbs(qset=batch) page_name = '' if breadcrumbs: if breadcrumbs[0][0] == 'Listing Form': page_name = 'Listing' else: page_name = 'Batch' request.breadcrumbs(breadcrumbs) context = { 'batch_questions_form': unicode(BatchQuestionsForm()), 'batch': batch, 'button_label': 'Save', 'id': 'assign-question-to-batch-form', 'library_questions': library_questions, 'question_filter_form': question_filter_form, 'page_name': page_name, 'redirect_url': '/qsets/%s/questions/' % qset_id } return render(request, 'set_questions/assign.html', context)
def assign(request, qset_id): batch = QuestionSet.get(id=qset_id) if batch.interviews.count(): error_message = "Questions cannot be assigned \ interviews has already been conducted: %s." % \ batch.name.capitalize() messages.error(request, error_message) return HttpResponseRedirect( reverse( 'qset_questions_page', args=( batch.pk, ))) if request.method == 'POST': data = dict(request.POST) last_question = batch.last_question_inline() lib_questions = QuestionTemplate.objects.filter( identifier__in=data.get('identifier', '')) if lib_questions: for lib_question in lib_questions: question = Question.objects.create( identifier=lib_question.identifier, text=lib_question.text, answer_type=lib_question.answer_type, qset=batch, ) # assign the options for option in lib_question.options.all(): QuestionOption.objects.create( question=question, text=option.text, order=option.order) if last_question: QuestionFlow.objects.create( question=last_question, next_question=question) else: batch.start_question = question batch.save() last_question = question #batch_questions_form = BatchQuestionsForm(batch=batch,\ #\data=request.POST, instance=batch) success_message = "Questions successfully assigned to %s: %s." % ( batch.verbose_name(), batch.name.capitalize()) messages.success(request, success_message) return HttpResponseRedirect( reverse( 'qset_questions_page', args=( batch.pk, ))) used_identifiers = [ question.identifier for question in batch.questions.all()] library_questions = QuestionTemplate.objects.exclude( identifier__in=used_identifiers).order_by('identifier') question_filter_form = QuestionFilterForm() # library_questions = question_filter_form.filter(library_questions) breadcrumbs = Question.edit_breadcrumbs(qset=batch) page_name = '' if breadcrumbs: if breadcrumbs[0][0] == 'Listing Form': page_name = 'Listing' else: page_name = 'Batch' request.breadcrumbs(breadcrumbs) context = { 'batch_questions_form': unicode( BatchQuestionsForm()), 'batch': batch, 'button_label': 'Save', 'id': 'assign-question-to-batch-form', 'library_questions': library_questions, 'question_filter_form': question_filter_form, 'page_name': page_name, 'redirect_url': '/qsets/%s/questions/' % qset_id} return render(request, 'set_questions/assign.html', context)