This documentation is meant for the technical people who will install crowdsourcing, tailor it for your website, and keep it running.
The example application is a great place to start. You can also review the producer’s documentation as that explains what all the fields are for and how to use them.
If you want to go directly to the source, these files are particularly important.
Prerequisites are:
- Django itself, of course – 1.1 or better.
- PIL
- django-positions
- sorl-thumbnail
- flickrapi (optional)
Django-crowdsourcing itself can be installed with pip:
$ # probably in a virtualenv ...
$ pip install django-crowdsourcing
The example application is a great resource for developers. It lays out a simple example of how to get all the gritty details working together. Perhaps even more importantly it contains a lot of very useful Javascript which you will probably want to include in your application.
crowdsourcing_requirements.txt is a pip requirements file that describes the basic requirements for crowdsourcing. example_app/example_app_requirements.txt has requirements necessary for the example app. You can install these requirements and the example app through steps like these:
$ easy_install pip
$ pip install mercurial
$ hg clone https://django-crowdsourcing.googlecode.com/hg/ django-crowdsourcing
$ cd django-crowdsourcing
django-crowdsourcing $ pip install -r crowdsourcing_requirements.txt
django-crowdsourcing $ pip install -r example_app/example_app_requirements.txt
Take whatever steps you need to install a database. Put the appropriate
settings in example_app/local_settings.py Perhaps your local_settings.py will
look something like this:
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_HOST = '127.0.0.1'
DATABASE_PORT = ''
DATABASE_NAME = 'my_database'
DATABASE_USER = 'me'
DATABASE_PASSWORD = 'my_password'
django-crowdsourcing $ cd example_app
django-crowdsourcing/example_app $ ./manage.py syncdb
django-crowdsourcing/example_app $ ./manage.py runserver
Crowdsourcing uses the terms “field” and “question” interchangeably. This is because in some contexts it makes sense to refer to the questions of a survey, while in other contexts you may want to think in terms of fields of a survey object.
The example application is a great place to look for guidance on how to set up your templates.
crowdsourcing.templatetags.crowdsourcing has a lot of useful templatetags. Each templatetag is a simple tag which makes it easy to use with both the Django and Mako templating systems. For example, in Django:
{% load crowdsourcing %}
{% yahoo_api %}
In Mako:
<% from crowdsourcing.templatetags import crowdsourcing %>
${crowdsourcing.yahoo_api()}
Create a crowdsourcing folder in your templates directory. You’ll need the following templates in that folder.
survey_detail.html
This template displays the survey entry form. The context is
embeded_survey_questions.html
This template displays just the questions and the submit button for the survey entry form. It’s used by the Javascript to embed survey entry forms. Reuse code between this template and survey_detail.html. The context is the same for survey_detail.html.
survey_report.html
This template displays survey reports. The context is
embeded_survey_report.html
You can also embed survey reports using the Javascript that comes with the example application. Embedded reports render with this template. As you would expect, you should reuse code between survey_report.html and embeded_surey_report.html.
See the context for survey_report.html
submission.html
This template renders the permalinks for individual submissions.
The context is
submission_for_map.html
The Javascript that comes with the example app, along with some template tags, renders Google Maps. You can click on icons which will pop a box up over the map with the contents of that submission. This is the template for that popped up box. Again, it makes sense to reuse template code between submission.html and submission_for_map.html.
See submission.html for the context.
The example app comes with some pretty handy Javascript. It embeds surveys and survey reports, renders charts and maps, and so on. As the Javascript generates a certain amount of HTML, it may not fit your site’s structure exactly so you’ll want to use it with caution. However, it’s still a great place to start and you may want to include it directly on your site.
Both the example application and WNYC’s website, crowdsourcing’s flagship site, use crowdsourcing’s Javascript. The Javascript assumes that all crowdsourcing urls are under /crowdsourcing/, i.e., you have a urls.py file with the line (r'^crowdsourcing/', include('crowdsourcing.urls')).
survey.js uses different markup for surveys that consist of a single choice type question. This markup allows you to enter such a survey with a single click.
These are the more important template tags. For a complete list, view the source at crowdsourcing/templatetags/crowdsourcying.py.
yahoo_api()
YUI charts and graphs are pretty slick. The example app is set up to do pie, bar, and line charts using YUI. You will want this tag in your page header to enable YUI.
jquery_and_google_api()
Make sure you set the CROWDSOURCING_GOOGLE_MAPS_API_KEY setting discussed below in Settings. Put this tag in your header to load both the Google Maps API and jQuery.
filters_as_ul(filters)
Use this template tag to render all the filters for a survey.
filter_as_li(filter)
If you want to stick some of your own filters in there, you can have more control over where the filters appear by rendering them individually.
yahoo_pie_chart(display, question, request_get)
Render a YUI pie chart.
yahoo_bar_chart(display, request_get)
Or a YUI bar chart.
yahoo_line_chart(display, request_get)
Or a YUI line chart.
google_map(display, question, report)
Or a Google Map.
simple_slideshow(display, question, request_GET, css)
You’ll need jQuery’s jcarousel to make this work. The example app uses <script type="text/javascript" src="/media/jquery.jcarousel.min.js"></script> in the page header.
load_maps_and_charts()
This simply writes out a script tag that calls function loadMapsAndCharts() defined in survey.js in the example app.
Tying it all together
Here, directly from the example app, is some effective code for rendering all the survey report displays in a survey report.
{% for display in report.get_survey_report_displays %}
{% if display.is_text %}
{{ display.annotation|safe }}
{% else %}{% if display.is_pie %}
{% for question in display.questions %}
{% yahoo_pie_chart display question request.GET %}
{% endfor %}
{% else %}{% if display.is_map %}
{% for question in display.questions %}
{% google_map display question report %}
{% endfor %}
{% else %}{% if display.is_bar %}
{% yahoo_bar_chart display request.GET %}
{% else %}{% if display.is_line %}
{% yahoo_line_chart display request.GET %}
{% else %}{% if display.is_slideshow %}
{% for question in display.questions %}
{% simple_slideshow display question request.GET "jcarousel-skin-tango" %}
{% endfor %}
{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}
{% endfor %}
{% load_maps_and_charts %}
submission_fields(submission, fields=None, page_answers=None, video_height=360, video_width=288)
This template tag renders all the answers in a single submission.
submissions(object_list, fields)
While this template tag renders all the submissions.
submission_link(submission, link_detail_survey_none=DETAIL_SURVEY_NONE.SURVEY)
This template tag creates a link that you would display at the end of a submission. As you display submissions on report pages, on their own permalink pages, and in maps, you want the link to point different places.
DETAIL_SURVEY_NONE.DETAIL = 1 # Point to the submission's permalink
DETAIL_SURVEY_NONE.SURVEY = 2 # Point to the submission's suvey's default survey report
DETAIL_SURVEY_NONE.NONE = 3 # Don't display a link.
paginator(survey, report, pages_to_link, page_obj)
On the survey report page you could use this template tag to display your pagination links.
Crowdsourcing does not dictate what ratings or comments system you use. However, a common use case is to sort submissions descending by their rating. Crowdsourcing provides a hook so you can arbitrarily modify the query object that pulls back submissions just before they display to accomplish just such a task.
Start by creating a function with this signature. To accomplish the use case above, you’ll also include some code like the following:
def my_pre_report_filter(submissions, report, request):
default_sort = "Rating" if report.sort_by_rating else ""
if "Rating" == request.GET.get("sort", default_sort):
# Sort by rating here.
submissions = submissions.order_by(...)
return submissions
Next, create this setting to let crowdsourcing know where to find your hook:
CROWDSOURCING_PRE_REPORT = 'my.app_path.my_pre_report_filter'
Crowdsourcing has an api that allows you to query submissions. The results return in reverse chronological order by the date they were submitted. If you are a logged in staff user all submissions and all fields will return regardless of whether or not they are public. Every result always has these fields with the exception of empty fields in xml such as the user when the user was not logged in:
It depends where your crowdsourcing root url is. If your urls.py file contains the line (r'^crowdsourcing/', include('crowdsourcing.urls')), then your url will look something like /crowdsourcing/submissions/<format>/?<filters>
<submissions>
<submission>
<submitted_at>2010-05-18T15:21:16</submitted_at>
<survey>test_survey</survey>
<user>dsmith</user>
<category>Republican</category>
<first_car>Saturn</category>
</submission>
<submission>
<submitted_at>2010-05-18T15:21:16</submitted_at>
<survey>test_survey</survey>
<category>Republican</category>
</submission>
</submissions>
You pass filters through query string parameters.
These filters are always available.
If you use the survey filter, you can also use specific filters from that survey. To see what parameters you use exactly for a particular survey, follow these steps:
Let’s say you have a survey with slug liberals-vs-conservatives with a choice type question with fieldname affiliation and options Liberal and Conservative. This url will pull up a human readable html version of all submissions for that survey.
/crowdsourcing/submissions/html/?survey=liberals-vs-conservatives
This will retrieve an xml report of all liberals in that survey.
/crowdsourcing/submissions/xml/?survey=liberals-vs-conservatives&affiliation=Liberal
This will retrieve a json report of the 10 most recent featured submissions across the whole site.
/crowdsourcing/submissions/json/?featured=true&limit=10
Crowdsourcing is set up to synchronously sync with Flickr when you save an answer. Asynchronously is ideal. Here’s how to set it up.
See CROWDSOURCING_SYNCHRONOUS_FLICKR_UPLOAD below for more details.
You can see all the possible configuration settings, and in some cases more detailed notes in crowdsourcing/settings.py.
CROWDSOURCING_MODERATE_SUBMISSIONS
This sets the default “Moderate submissions” value of surveys.
CROWDSOURCING_IMAGE_UPLOAD_PATTERN
Relative to your MEDIA directory.
CROWDSOURCING_FLICKR_API_KEY
If you interface with Flickr for photo uploads you’ll need to set this property. In fact there are several authentication properties you’ll need to set including CROWDSOURCING_FLICKR_API_SECRET, CROWDSOURCING_FLICKR_TOKEN, and CROWDSOURCING_FLICKR_FROB. See crowdsourcing/settings.py for a detail explanation of how I used the Django shell to retrieve the frob and token.
CROWDSOURCING_FLICKR_LIVE
Are Flickr photos live by default?
CROWDSOURCING_FLICKR_TOKENCACHE_PATH
Your application will need permission to this file path.
CROWDSOURCING_PRE_REPORT
This path to a function is discussed in detail under “Pre-Report Filter.”
CROWDSOURCING_SURVEY_EMAIL_FROM
You can set up individual surveys to e-mail a list of people when users create new submissions. This setting says where that e-mail will come from.
CROWDSOURCING_SURVEY_ADMIN_SITE
This site is for the notification emails that crowdsourcing sends when a user enters a survey. The default is the site the user entered the survey on.
CROWDSOURCING_OEMBED_EXPAND
You can set a custom def oembed_expand(url, **opts) which takes the url to a video and returns html embed code. Use the form path.to.my_function
CROWDSOURCING_LOGIN_VIEW
What URL should crowdsourcing redirect users to if they try to enter a survey that requires a login?
CROWDSOURCING_VIDEO_URL_PATTERNS
youtube has a lot of characters in their ids now so use [^&]. youtube also likes to add additional query arguments, so no trailing $. If you have oembed installed, crowdsourcing uses the oembed configuration and ignores this.
CROWDSOURCING_GOOGLE_MAPS_API_KEY
crowdsourcing.templatetags.crowdsourcing.google_map uses this setting.
CROWDSOURCING_EXTRA_THUMBNAILS
A dictionary of extra thumbnails for Submission.image_answer, which is a sorl ImageWithThumbnailsField. For example, {'slideshow': {'size': (620, 350)}}
CROWDSOURCING_SYNCHRONOUS_FLICKR_UPLOAD
Syncing flickr synchronously means that crowdsourcing will attempt to sync on save. This is not ideal because it makes a slow user experience, and failed synching goes unresolved. Crowdsourcing syncs synchronously by default however because asynchronously synching is more difficult to set up. crowdsourcing/tasks.py attempts to set up a celery task, so if you have celery running to can just make this setting false.