def wrapper(*args, **kwargs): question_slug = kwargs['question_slug'] the_user = args[0].user try: the_question = MultipleChoiceQuestion.objects.get( slug=question_slug) except CustomAppError as e: return DefaultErrorPage(e, "Could not find the question specified.") # the current user can only access his questions, not other people's if (the_question.linked_survey.author.id != the_user.id): return DefaultErrorPage( mesg="You do not have permission to view this question.") return fn(*args, **kwargs)
def wrapper(*args, **kwargs): question_slug = kwargs['question_slug'] the_user = args[0].user the_question = MultipleChoiceQuestion.objects.get(slug=question_slug) if (Pub_Or_Not == 'Not_Published'): if (the_question.linked_survey.publishing_set.count() > 0): return DefaultErrorPage( mesg= "This question is already published and cannot be edited.") if (Pub_Or_Not == 'Published'): if (the_question.linked_survey.publishing_set.count() == 0): return DefaultErrorPage( mesg="This question is not published yet.") return fn(*args, **kwargs)
def DeleteQuestion(request, question_slug=''): if request.method != "POST": return DefaultErrorPage(mesg="Delete does not work with GET.") theQuestion = GetQuestionFromSlug(question_slug) try: DeleteRelatedPublishings(theQuestion) linked_survey = theQuestion.linked_survey theQuestion.delete() linked_survey.delete() #need to add transcation/rollback here except (DatabaseError, IntegrityError) as e: return DefaultErrorPage( e, "Could not delete this question due to a database error.") return utils.custom_redirect('ShowQuestionsList', just_deleted_question=True)
def RespondToQuestion(request, question_slug='', answer_slug='', redirect_url='', **kwargs): #see if question is already answered by this IP address try: theQuestion = GetQuestionFromSlug(question_slug) except CustomAppError as e: return DefaultErrorPage(e, "Could not find the question you specified.") try: theAnswer = GetAnswerFromSlug(answer_slug) except CustomAppError as e: return DefaultErrorPage(e, "Could not find the answer you specified.") # turns out blocking by IP is not effective, you could block an entire house # as it will use the IP assigned by the ISP # instead we will use cookies #source_ip_addr = GetIpAddress(request) #turn OFF while developing...turn on later if settings.COOKIE_BLOCKING == 'True': if ThisPersonAlreadyResponded(request, theQuestion): return PageForIPAddrAlreadyVoted(theQuestion) #if we made it here, the user hasn't already replied. Return success #although actually the AJAX call this page makes will actually cause the vote to register #had to do that, as Heroku or FB or some non-humans were sending GET to this page #and registering votes which distorting the vote return PageForUserResponseAccepted(theQuestion, theAnswer, request, redirect_url)
def ShowResults(request, question_slug, IsAjax=False): template = 'show_question_details.html' if IsAjax == False else 'answer_and_chart_sub_template.html' try: theQuestion = GetQuestionFromSlug(question_slug) except CustomAppError as e: return DefaultErrorPage(e, mesg="Could not find the question specified.") #get the answer choices and get the vote counts theAnswers = theQuestion.multiplechoiceansweritem_set.all() vote_tally, total_votes = GetVoteTally(theAnswers) is_published = (theQuestion.linked_survey.publishing_set.count() > 0) return render_to_response(template, {'question' : theQuestion, 'answers' : theAnswers, 'is_published' : \ is_published, 'is_results_page' : True, 'vote_tally' : json.dumps(vote_tally), 'total_votes': total_votes}, \ context_instance=RequestContext(request))
def AddQuestion(request, **kwargs): template = 'edit_question.html' theUser = request.user #inline formset is a good tool to use to get answers that have a foreign key to a question MultipleChoiceAnswerItemFormset = inlineformset_factory( MultipleChoiceQuestion, MultipleChoiceAnswerItem, form=MultipleChoiceAnswerItemModelForm, formset=MultipleChoiceAnswerItemModelFormset, extra=2, can_delete=True) #POST means user has submitted the form with new question and answer options if request.method == 'POST': #prefix helps distinguish forms from each other form = MultipleChoiceQuestionModelForm(request.POST, prefix='Question') formset = MultipleChoiceAnswerItemFormset(request.POST, prefix='Answer') if form.is_valid() and formset.is_valid(): try: #create new question but don't commit to DB yet as we have to #create the survey object first as the question has a foreign key to the survey object new_question = form.save(commit=False) #create new survey, for now each question has a survey object. no more than 1 question per survey for now new_survey = MultipleChoiceSurvey( create_date=datetime.datetime.now(), author=theUser) new_survey.save() the_new_id = new_survey.id new_question.linked_survey = MultipleChoiceSurvey.objects.get( id=the_new_id) new_question.save() new_question_in_db = MultipleChoiceQuestion.objects.get( id=new_question.id) new_answers = formset.save(commit=False) for a in new_answers: a.linked_question = new_question_in_db a.save() #To-do: need to actually do a rollback of all changes here upon getting an unlikely DB error #should use Django's atomic.transaction probably except (DatabaseError, IntegrityError) as e: return DefaultErrorPage( e, "Your question could not be saved due to some problem with the database. Please try again later." ) #redirect to ShowQuestionDetails when done adding a question return HttpResponseRedirect( reverse('ShowQuestionDetails', kwargs={'question_slug': new_question_in_db.slug})) else: #if form is not valid, i.e. the new question has a problem, just rerender the form with errors return render_to_response(template, { 'form': form, 'formset': formset, 'add_or_edit': 'add' }, context_instance=RequestContext(request)) # if method is GET show a blank form else: form = MultipleChoiceQuestionModelForm(prefix='Question') formset = MultipleChoiceAnswerItemFormset(prefix='Answer') return render_to_response(template, { 'form': form, 'formset': formset, 'add_or_edit': 'add' }, context_instance=RequestContext(request))
def PublishQuestionToFacebook(request, graph, question_slug=''): # debugprint('starting publish func: ' + str(datetime.datetime.now())) # debugprint('method=' + request.method) # #should never happen, but if we don't get a graph object passed in from the facebook decorator, #we must go back to the question page with an error if not graph: return utils.custom_redirect('ShowQuestionDetails', question_slug, fb_post_error=True) # skip exception handling here, the decorator already checked theQuestion = GetQuestionFromSlug(question_slug) # #first create a publishing object to represent that this question is now in 'published' state # and no longer be changed try: IsAlreadyPublished = (theQuestion.linked_survey.publishing_set.count() > 0) new_publishing = FacebookPublishing( linked_survey=theQuestion.linked_survey, publish_date=datetime.datetime.now(), dummy_field='dummy_data') new_publishing.save() #create bit.ly url's for the voting url's theAnswers = theQuestion.multiplechoiceansweritem_set.all().order_by( 'pk') ViewHelpers.CreateURLsForAnswersIfNeeded(question_slug, IsAlreadyPublished, theAnswers) #need to add rollback/transaction here, actually the whole view should be in a transaction #and rolled back if any problems except (DatabaseError, IntegrityError) as e: return DefaultErrorPage( e, mesg= "There was a problem posting your question to facebook due to a database or other error. Please try again later." ) fb_post_str = ConstructFBPostForQuestion(theQuestion, theAnswers) # debugprint('before call to post to FB ' + str(datetime.datetime.now()) + ' ' + request.method) # debugprint('method=' + request.method) # #result = graph.set('me/feed', message=fb_post_str) #creates an asynchronous task using RQ to post to Facebook passing it the access token # and post text try: asynch_post_job = ViewHelpers.post_to_fb_async.delay( graph.access_token, fb_post_str) except Exception as e: return utils.custom_redirect('ShowQuestionDetails', question_slug, fb_post_error=True) # debugprint('after call to post to FB ' + str(datetime.datetime.now()) + ' ' + request.method) # debugprint('method=' + request.method) return utils.custom_redirect('ShowQuestionDetails', question_slug, just_published_on_FB=True)
def EditQuestion(request, question_slug='', **kwargs): #def inline_formset(request, form_class, template): template = 'edit_question.html' MultipleChoiceAnswerItemFormset = inlineformset_factory( MultipleChoiceQuestion, MultipleChoiceAnswerItem, form=MultipleChoiceAnswerItemModelForm, formset=MultipleChoiceAnswerItemModelFormset, extra=1, can_delete=True) theQuestion = MultipleChoiceQuestion.objects.get(slug=question_slug) # if POST the user submitted changes to the question. So validate and save to DB if request.method == 'POST': form = MultipleChoiceQuestionModelForm(request.POST, prefix="Question", instance=theQuestion) formset = MultipleChoiceAnswerItemFormset(request.POST, prefix="Answer", instance=theQuestion) is_question_form_valid = form.is_valid() is_answer_formset_valid = formset.is_valid() if is_question_form_valid and is_answer_formset_valid: try: form.save() formset.save() except (DatabaseError, IntegrityError) as e: return DefaultErrorPage( e, mesg= "Could not save your changes to the question due to a database error. Try again later." ) #redirect to the show the updated question return HttpResponseRedirect( reverse('ShowQuestionDetails', kwargs={'question_slug': question_slug})) else: #form is invalid, re-render form with errors return render_to_response(template, { 'form': form, 'formset': formset, 'question': theQuestion, 'add_or_edit': 'edit' }, context_instance=RequestContext(request)) #handle GET #render the form else: form = MultipleChoiceQuestionModelForm(prefix="Question", instance=theQuestion) formset = MultipleChoiceAnswerItemFormset(prefix="Answer", instance=theQuestion) return render_to_response(template, { 'form': form, 'formset': formset, 'question': theQuestion, 'add_or_edit': 'edit' }, context_instance=RequestContext(request))