def api_response(request, data, callback=None, format='json'): # http://www.loggly.com/blog/2011/12/enabling-cors-in-django-piston/ # for how to enable CORS request_method = request.method.upper() if request_method in ["OPTIONS", "HEAD"]: response = HttpResponse() elif isinstance(data, HttpResponseRedirect): response = data elif callback: body = u'%s(%s);' % (callback, dumps(data)) response = HttpResponse(body, mimetype='application/javascript') elif format == 'html': response = HttpResponse(data) else: response = HttpResponse(mimetype='application/json') dump(data, response) origin = request.META.get('HTTP_REFERER', '') or \ request.META.get('HTTP_ORIGIN', '') allowed = allow_origin_sites() if origin: allowed = [a for a in allowed if origin.find(a) >= 0] response["Access-Control-Allow-Origin"] = " ".join(allowed) response['Access-Control-Allow-Methods'] = \ 'POST, GET, OPTIONS, HEAD, PUT, DELETE' response["Access-Control-Allow-Headers"] = 'Authorization' response["Access-Control-Allow-Credentials"] = 'true' return response
def location_question_results( request, question_id, limit_map_answers, survey_report_slug=""): question = get_object_or_404(Question.objects.select_related("survey"), pk=question_id, answer_is_public=True) is_staff = request.user.is_staff if not question.survey.can_have_public_submissions() and not is_staff: raise Http404 featured = limit_results_to = False if survey_report_slug: survey_report = get_object_or_404(SurveyReport.objects, survey=question.survey, slug=survey_report_slug) featured = survey_report.featured limit_results_to = survey_report.limit_results_to icon_lookup = {} icon_questions = question.survey.icon_questions() for icon_question in icon_questions: icon_by_answer = {} for (option, icon) in icon_question.parsed_option_icon_pairs(): if icon: icon_by_answer[option] = icon answer_set = icon_question.answer_set.all() for answer in answer_set.select_related("question"): if answer.value in icon_by_answer: icon = icon_by_answer[answer.value] icon_lookup[answer.submission_id] = icon answers = question.answer_set.filter( ~Q(latitude=None), ~Q(longitude=None)).order_by("-submission__submitted_at") if not is_staff: answers = answers.filter(submission__is_public=True) if featured: answers = answers.filter(submission__featured=True) answers = extra_from_filters( answers, "submission_id", question.survey, request.GET) limit_map_answers = int(limit_map_answers) if limit_map_answers else 0 if limit_map_answers or limit_results_to: answers = answers[:min(filter(None, [limit_map_answers, limit_results_to, ]))] entries = [] view = "survey.views.submission_for_map" for answer in answers: kwargs = {"id": answer.submission_id} d = { "lat": answer.latitude, "lng": answer.longitude, "url": reverse(view, kwargs=kwargs)} if answer.submission_id in icon_lookup: d["icon"] = icon_lookup[answer.submission_id] entries.append(d) response = HttpResponse(mimetype='application/json') dump({"entries": entries}, response) return response
def submissions(request, format): """ Use this view to make arbitrary queries on submissions. If the user is a logged in staff member, ignore submission.is_public, question.answer_is_public, and survey.can_have_public_submissions. Use the query string to pass keys and values. For example, /crowdsourcing/submissions/?survey=my-survey will return all submissions for the survey with slug my-survey. survey - the slug for the survey user - the username of the submittor. Leave blank for submissions without a logged in user. submitted_from and submitted_to - strings in the format YYYY-mm-ddThh:mm:ss For example, 2010-04-05T13:02:03 featured - A blank value, 'f', 'false', 0, 'n', and 'no' all mean ignore the featured flag. Everything else means display only featured. You can also use filters in the survey report sense. Rather than document exactly what parameters you would pass, follow these steps to figure it out: 1. Enable filters on your survey and the questions you want to filter on. 2. Go to the report page and fill out the filters you want. 3. Click Submit. 4. Examine the query string of the page you end up on and note which parameters are filled out. Use those same parameters here. """ format = format.lower() if format not in FORMAT_CHOICES: msg = ("%s is an unrecognized format. Crowdsourcing recognizes " "these: %s") % (format, ", ".join(FORMAT_CHOICES)) return HttpResponse(msg) is_staff = request.user.is_authenticated() and request.user.is_staff if is_staff: results = Submission.objects.all(status=Submission.COMPLETED) else: # survey.can_have_public_submissions is complicated enough that # we'll check it in Python, not the database. results = Submission.objects.filter(is_public=True, status=Submission.COMPLETED) results = results.select_related("survey", "user") get = request.GET.copy() limit = int(get.pop("limit", [0])[0]) keys = get.keys() basic_filters = ( 'survey', 'user', 'submitted_from', 'submitted_to', 'featured', 'is_public') if is_staff: basic_filters += BALLOT_STUFFING_FIELDS survey_slug = "" for field in [f for f in keys if f in basic_filters]: value = get[field] search_field = field if 'survey' == field: search_field = 'survey__slug' survey_slug = value elif 'user' == field: if '' == value: value = None else: search_field = 'user__username' elif field in ('submitted_from', 'submitted_to'): date_format = "%Y-%m-%dT%H:%M:%S" try: value = datetime.strptime(value, date_format) except ValueError: return HttpResponse( ("Invalid %s format. Try, for example, " "%s") % (field, datetime.now().strftime(date_format),)) if 'submitted_from' == field: search_field = 'submitted_at__gte' else: search_field = 'submitted_at__lte' elif field in ('featured', 'is_public',): falses = ('f', 'false', 'no', 'n', '0',) value = len(value) and not value.lower() in falses # search_field is unicode but needs to be ascii. results = results.filter(**{str(search_field): value}) get.pop(field) def get_survey(): survey = Survey.objects.get(slug=survey_slug) get_survey = lambda: survey return survey if get: if survey_slug: results = extra_from_filters( results, "survey_submission.id", get_survey(), get) else: message = ( "You've got a couple of extra filters here, and we " "aren't sure what to do with them. You may have just " "misspelled one of the basic filters (%s). You may have a " "filter from a particular survey in mind. In that case, just " "include survey=my-survey-slug in the query string. You may " "also be trying to pull some hotshot move like, \"Get me all " "submissions that belong to a survey with a filter named '%s' " "that match '%s'.\" Crowdsourcing could support this, but it " "would be pretty inefficient and, we're guessing, pretty " "rare. If that's what you're trying to do I'm afraid you'll " "have to do something more complicated like iterating through " "all your surveys.") item = get.items()[0] message = message % (", ".join(basic_filters), item[0], item[1]) return HttpResponse(message) if not is_staff: if survey_slug: if not get_survey().can_have_public_submissions(): results = [] else: rs = [r for r in results if r.survey.can_have_public_submissions()] results = rs if limit: results = results[:limit] answer_lookup = get_all_answers(results, include_private_questions=is_staff) result_data = [] for r in results: data = r.to_jsondata(answer_lookup, include_private_questions=is_staff) result_data.append(data) for data in result_data: data.update(data["data"]) data.pop("data") def get_keys(): key_lookup = {} for data in result_data: for key in data.keys(): key_lookup[key] = True return sorted(key_lookup.keys()) if format == 'json': response = HttpResponse(mimetype='application/json') dump(result_data, response) elif format == 'csv': response = HttpResponse(mimetype='text/csv') writer = csv.writer(response) keys = get_keys() writer.writerow(keys) for data in result_data: row = [] for k in keys: row.append((u"%s" % _encode(data.get(k, ""))).encode("utf-8")) writer.writerow(row) elif format == 'xml': doc = Document() submissions = doc.createElement("submissions") doc.appendChild(submissions) for data in result_data: submission = doc.createElement("submission") submissions.appendChild(submission) for key, value in data.items(): if value: cell = doc.createElement(key) submission.appendChild(cell) cell.appendChild(doc.createTextNode(u"%s" % value)) response = HttpResponse(doc.toxml(), mimetype='text/xml') elif format == 'html': # mostly for debugging. keys = get_keys() results = [ "<html><body><table>", "<tr>%s</tr>" % "".join(["<th>%s</th>" % k for k in keys])] for data in result_data: cell = "<td>%s</td>" cells = [cell % _encode(data.get(key, "")) for key in keys] results.append("<tr>%s</tr>" % "".join(cells)) results.append("</table></body></html>") response = HttpResponse("\n".join(results)) else: return HttpResponse("Unsure how to handle %s format" % format) return response