def questionnaire(request, runcode=None, qs=None): """ Process submit answers (if present) and redirect to next page If this is a POST request, parse the submitted data in order to store all the submitted answers. Then return to the next questionset or return a completed response. If this isn't a POST request, redirect to the main page. We only commit on success, to maintain consistency. We also specifically rollback if there were errors processing the answers for this questionset. """ if use_session: session_runcode = request.session.get('runcode', None) if session_runcode is not None: runcode = session_runcode session_qs = request.session.get('qs', None) if session_qs is not None: qs = session_qs # if runcode provided as query string, redirect to the proper page if not runcode: runcode = request.GET.get('runcode') if not runcode: return HttpResponseRedirect("/") else: if not use_session: args = [runcode, ] else: request.session['runcode'] = runcode args = [] return HttpResponseRedirect(reverse("questionnaire", args=args)) runinfo = get_runinfo(runcode) if not runinfo: commit() return HttpResponseRedirect('/') if runinfo.questionset.questionnaire.admin_access_only == 1: if not request.user.is_superuser: return HttpResponseRedirect(runinfo.questionset.questionnaire.redirect_url) # let the runinfo have a piggy back ride on the request # so we can easily use the runinfo in places like the question processor # without passing it around request.runinfo = runinfo if not qs: # Only change the language to the subjects choice for the initial # questionnaire page (may be a direct link from an email) if hasattr(request, 'session'): request.session['django_language'] = runinfo.subject.language translation.activate(runinfo.subject.language) if 'lang' in request.GET: return set_language(request, runinfo, request.path) # -------------------------------- # --- Handle non-POST requests --- # -------------------------------- if request.method != "POST": if qs is not None: qs = get_object_or_404(QuestionSet, sortid=qs, questionnaire=runinfo.questionset.questionnaire) if runinfo.random.startswith('test:'): pass # ok for testing elif qs.sortid > runinfo.questionset.sortid: # you may jump back, but not forwards return redirect_to_qs(runinfo, request) runinfo.questionset = qs runinfo.save() commit() # no questionset id in URL, so redirect to the correct URL if qs is None: return redirect_to_qs(runinfo, request) questionset_start.send(sender=None, runinfo=runinfo, questionset=qs) return show_questionnaire(request, runinfo) # ------------------------------------- # --- Process POST with QuestionSet --- # ------------------------------------- # if the submitted page is different to what runinfo says, update runinfo # XXX - do we really want this? qs = request.POST.get('questionset_id', qs) try: qsobj = QuestionSet.objects.filter(pk=qs)[0] if qsobj.questionnaire == runinfo.questionset.questionnaire: if runinfo.questionset != qsobj: runinfo.questionset = qsobj runinfo.save() except: pass questionnaire = runinfo.questionset.questionnaire questionset = runinfo.questionset # to confirm that we have the correct answers expected = questionset.questions() items = request.POST.items() extra = {} # question_object => { "ANSWER" : "123", ... } # this will ensure that each question will be processed, even if we did not receive # any fields for it. Also works to ensure the user doesn't add extra fields in for x in expected: items.append((u'question_%s_Trigger953' % x.number, None)) # generate the answer_dict for each question, and place in extra for item in items: key, value = item[0], item[1] if key.startswith('question_'): answer = key.split("_", 2) question = get_question(answer[1], questionnaire) if not question: logging.warn("Unknown question when processing: %s" % answer[1]) continue extra[question] = ans = extra.get(question, {}) if (len(answer) == 2): ans['ANSWER'] = value elif (len(answer) == 3): ans[answer[2]] = value else: logging.warn("Poorly formed form element name: %r" % answer) continue extra[question] = ans errors = {} for question, ans in extra.items(): if not question_satisfies_checks(question, runinfo): continue if u"Trigger953" not in ans: logging.warn("User attempted to insert extra question (or it's a bug)") continue try: cd = question.getcheckdict() # requiredif is the new way depon = cd.get('requiredif', None) or cd.get('dependent', None) if depon: depparser = BooleanParser(dep_check, runinfo, extra) if not depparser.parse(depon): # if check is not the same as answer, then we don't care # about this question plus we should delete it from the DB delete_answer(question, runinfo.subject, runinfo.runid) if cd.get('store', False): runinfo.set_cookie(question.number, None) continue add_answer(runinfo, question, ans) if cd.get('store', False): runinfo.set_cookie(question.number, ans['ANSWER']) except AnswerException, e: errors[question.number] = e except Exception: logging.exception("Unexpected Exception") rollback() raise
def questionnaire(request, runcode=None, qs=None): """ Process submit answers (if present) and redirect to next page If this is a POST request, parse the submitted data in order to store all the submitted answers. Then return to the next questionset or return a completed response. If this isn't a POST request, redirect to the main page. We only commit on success, to maintain consistency. We also specifically rollback if there were errors processing the answers for this questionset. """ if use_session: session_runcode = request.session.get('runcode', None) if session_runcode is not None: runcode = session_runcode session_qs = request.session.get('qs', None) if session_qs is not None: qs = session_qs # if runcode provided as query string, redirect to the proper page if not runcode: runcode = request.GET.get('runcode') if not runcode: return HttpResponseRedirect("/") else: if not use_session: args = [ runcode, ] else: request.session['runcode'] = runcode args = [] return HttpResponseRedirect(reverse("questionnaire", args=args)) runinfo = get_runinfo(runcode) if not runinfo: commit() return HttpResponseRedirect('/') if runinfo.questionset.questionnaire.admin_access_only == 1: if not request.user.is_superuser: return HttpResponseRedirect( runinfo.questionset.questionnaire.redirect_url) # let the runinfo have a piggy back ride on the request # so we can easily use the runinfo in places like the question processor # without passing it around request.runinfo = runinfo if not qs: # Only change the language to the subjects choice for the initial # questionnaire page (may be a direct link from an email) if hasattr(request, 'session'): request.session['django_language'] = runinfo.subject.language translation.activate(runinfo.subject.language) if 'lang' in request.GET: return set_language(request, runinfo, request.path) # -------------------------------- # --- Handle non-POST requests --- # -------------------------------- if request.method != "POST": if qs is not None: qs = get_object_or_404( QuestionSet, sortid=qs, questionnaire=runinfo.questionset.questionnaire) if runinfo.random.startswith('test:'): pass # ok for testing elif qs.sortid > runinfo.questionset.sortid: # you may jump back, but not forwards return redirect_to_qs(runinfo, request) runinfo.questionset = qs runinfo.save() commit() # no questionset id in URL, so redirect to the correct URL if qs is None: return redirect_to_qs(runinfo, request) questionset_start.send(sender=None, runinfo=runinfo, questionset=qs) return show_questionnaire(request, runinfo) # ------------------------------------- # --- Process POST with QuestionSet --- # ------------------------------------- # if the submitted page is different to what runinfo says, update runinfo # XXX - do we really want this? qs = request.POST.get('questionset_id', qs) try: qsobj = QuestionSet.objects.filter(pk=qs)[0] if qsobj.questionnaire == runinfo.questionset.questionnaire: if runinfo.questionset != qsobj: runinfo.questionset = qsobj runinfo.save() except: pass questionnaire = runinfo.questionset.questionnaire questionset = runinfo.questionset # to confirm that we have the correct answers expected = questionset.questions() items = request.POST.items() extra = {} # question_object => { "ANSWER" : "123", ... } # this will ensure that each question will be processed, even if we did not receive # any fields for it. Also works to ensure the user doesn't add extra fields in for x in expected: items.append((u'question_%s_Trigger953' % x.number, None)) # generate the answer_dict for each question, and place in extra for item in items: key, value = item[0], item[1] if key.startswith('question_'): answer = key.split("_", 2) question = get_question(answer[1], questionnaire) if not question: logging.warn("Unknown question when processing: %s" % answer[1]) continue extra[question] = ans = extra.get(question, {}) if (len(answer) == 2): ans['ANSWER'] = value elif (len(answer) == 3): ans[answer[2]] = value else: logging.warn("Poorly formed form element name: %r" % answer) continue extra[question] = ans errors = {} for question, ans in extra.items(): if not question_satisfies_checks(question, runinfo): continue if u"Trigger953" not in ans: logging.warn( "User attempted to insert extra question (or it's a bug)") continue try: cd = question.getcheckdict() # requiredif is the new way depon = cd.get('requiredif', None) or cd.get('dependent', None) if depon: depparser = BooleanParser(dep_check, runinfo, extra) if not depparser.parse(depon): # if check is not the same as answer, then we don't care # about this question plus we should delete it from the DB delete_answer(question, runinfo.subject, runinfo.runid) if cd.get('store', False): runinfo.set_cookie(question.number, None) continue add_answer(runinfo, question, ans) if cd.get('store', False): runinfo.set_cookie(question.number, ans['ANSWER']) except AnswerException, e: errors[question.number] = e except Exception: logging.exception("Unexpected Exception") rollback() raise
if cd.get('store', False): runinfo.set_cookie(question.number, None) continue add_answer(runinfo, question, ans) if cd.get('store', False): runinfo.set_cookie(question.number, ans['ANSWER']) except AnswerException, e: errors[question.number] = e except Exception: logging.exception("Unexpected Exception") rollback() raise if len(errors) > 0: res = show_questionnaire(request, runinfo, errors=errors) rollback() return res questionset_done.send(sender=None, runinfo=runinfo, questionset=questionset) next = questionset.next() while next and not questionset_satisfies_checks(next, runinfo): next = next.next() runinfo.questionset = next runinfo.save() if use_session: request.session['prev_runcode'] = runinfo.random if next is None: # we are finished return finish_questionnaire(request, runinfo, questionnaire)
if cd.get('store', False): runinfo.set_cookie(question.number, None) continue add_answer(runinfo, question, ans) if cd.get('store', False): runinfo.set_cookie(question.number, ans['ANSWER']) except AnswerException, e: errors[question.number] = e except Exception: logging.exception("Unexpected Exception") rollback() raise if len(errors) > 0: res = show_questionnaire(request, runinfo, errors=errors) rollback() return res questionset_done.send(sender=None, runinfo=runinfo, questionset=questionset) next = questionset.next() while next and not questionset_satisfies_checks(next, runinfo): next = next.next() runinfo.questionset = next runinfo.save() if use_session: request.session['prev_runcode'] = runinfo.random if next is None: # we are finished
def db_action_with_rollback(m): m.importance = 5 m.save() compat.rollback()
def db_action_with_rollback(m): m.importance = 5 sid = django.db.transaction.savepoint() m.save() compat.rollback(None, sid)