a Django waiting list app
Python Other
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
pinax Use pinax-templates Jan 27, 2018


Pinax Waiting List

CircleCi Codecov

Table of Contents

About Pinax

Pinax is an open-source platform built on the Django Web Framework. It is an ecosystem of reusable Django apps, themes, and starter project templates. This collection can be found at http://pinaxproject.com.



pinax-waitinglist is an app for Django sites for collecting user emails on a waiting list before a site has launched. It also provides basic survey capabilities to gather information from your potential users.

For an out-of-the-box Django project already set up with pinax-waitinglist and Bootstrap templates, see the Pinax waitinglist starter project.

Supported Django and Python versions

Django \ Python 2.7 3.4 3.5 3.6
1.11 * * * *
2.0 * * *



Install the development version:

$ pip install pinax-waitinglist

Add pinax-waitinglist to your INSTALLED_APPS setting:

    # other apps

Run migrations:

$ python manage.py migrate

Add pinax.waitinglist.urls to your project urlpatterns:

urlpatterns = [
    # other urls
    url(r"^waitinglist/", include("pinax.waitinglist.urls", namespace="pinax_waitinglist")),


List Signup

The most basic usage would be to direct users to a page where they can provide their email address to be notified of updates:

Add a TemplateView for a landing page to your urls.py:

# project/urls.py

from django.views.generic import TemplateView

urlpatterns = [
    # other urls
    url(r"^$", TemplateView.as_view(template_name="waitinglist/list_signup.html"), name="home"),

Update your template directories in settings.py:

# project/settings.py
        'DIRS': [
            # other dirs
            os.path.join(BASE_DIR, "templates"),

Add list_signup.html template:

<!-- templates/waitinglist/list_signup.html -->

<div class="site-wrapper-inner">
    <div class="cover-container">
        <div class="inner cover">
            <h1 class="cover-heading">Sign up on our waiting list!</h1>
            <p class="lead">
                Once this site is ready to launch, you will be emailed.
            {% if form.email.errors %}
                <b>{{ form.email.errors.0 }}</b>
            {% endif %}
            {% url "waitinglist_list_signup" as url %}
            <form method="POST" action="{{ url }}" class="form-inline">
                {% csrf_token %}
                <div class="form-group">
                    <label class="sr-only" for="id_email">Email address</label>
                    <input type="email" name="email" class="form-control input-lg" id="id_email" placeholder="your@email.com">
                <button class="btn btn-default btn-lg">Submit</button>
        <div class="mastfoot">
            <div class="inner">
                <p>{% include "_footer.html" %}</p>

Add a success template success.html:

<!-- templates/waitinglist/success.html -->

<div class="site-wrapper-inner">
    <div class="cover-container">
        <div class="inner cover">
            <h1 class="cover-heading">Thank you!</h1>
            <p class="lead">You are on the list. We will notify you know when this site launches.</p>
                If you have any questions, feel free to email <a href="mailto:info@example.com"><b>info@example.com</b></a>.
        <div class="mastfoot">
            <div class="inner">
                <p>{% include "_footer.html" %}</p>


If you would like to offer a survey after users enter their email:

A survey will need to be created with one or more questions. Surveys and their questions are accessed through the admin interface.

# Add a survey

# Add questions to an existing survey

Add survey.html template:

<!-- templates/waitinglist/survey.html -->

<div class="site-wrapper-inner">
    <div class="cover-container">
        <div class="inner cover">
            <h1 class="cover-heading">Survey</h1>
            <p class="lead">Do you have a moment to answer a few qustions?</p>
                {% csrf_token %}
                {{ form }}
                <button type="submit" class="btn btn-default btn-lg">Submit</button>
        <div class="mastfoot">
            <div class="inner">
                <p>{% include "_footer.html" %}</p>

Email Survey to existing emails

Existing emails can be emailed surveys through a django command, mail_out_survey_links .

A SITE object is passed to both of the following templates, if you haven't enabled the sites framework yet, you will need to do so before proceeding. Additional information on enabling can be found at The “sites” framework.

Add survey_invite_subject.txt template:

    {# templates/waitinglist/survey_invite_subject.txt #}

    Survey from {{ site.name }}

Add survey_invite_body.txt template:

    {# templates/waitinglist/survey_invite_body.txt #}

    Please take a moment to complete a brief survey from Example.com:
    {{ protocol }}://www.{{ site.domain }}{% url 'waitinglist_survey' instance.code %}

Send survey emails:

$ python manage.py mail_out_survey_links

Campaigns and Referrals

Campaigns work by just taking the querystring parameter wlc if present in querystring and records the value to the waitinglist entry. This is useful if you want to track conversions of a particular ad campaign. You can set, for instance, https://mysite.com/?wlc=c1, as the url for the ad. when people click on the ad, and signup, c1 will be added to their entry and is viewable in the admin.

Referrals work the same as campaigns but work automatically. If there a value in request.META["HTTP_REFERER"] when landing on the signup page, the value will get required in the referral field of the waitinglist entry.



Defaults to SECRET_KEY

This is used for generating the hash for pinax.waitinglist.models.SurveyInstance.code.


Defaults to HTTP

Provided as context in certain emails for URL building.


Management Commands


Email links to survey instances for those that never saw a survey. Retrieves the currently active Survey, and filters WaitingListEntry where SurveyInstance is null.

Uses templates waitinglist/survey_invite_subject.txt & waitinglist/survey_invite_body.txt for emails.


Default templates are provided by the pinax-templates app in the waitinglist section of that project.

Reference pinax-templates installation instructions to include these templates in your project.

View live pinax-templates examples and source at Pinax Templates!

Customizing Templates

Override the default pinax-templates templates by copying them into your project subdirectory pinax/waitinglist/ on the template path and modifying as needed.

For example if your project doesn't use Bootstrap, copy the desired templates then remove Bootstrap and Font Awesome class names from your copies. Remove class references like class="btn btn-success" and class="icon icon-pencil" as well as bootstrap from the {% load i18n bootstrap %} statement. Since bootstrap template tags and filters are no longer loaded, you'll also need to update {{ form|bootstrap }} to {{ form }} since the "bootstrap" filter is no longer available.


Rendered by ajax_list_signup view when form is not valid and gets passed form (WaitingListEntryForm) in context.


Rendered by ajax_list_signup view when form is valid.

User-Provided Templates

Create these templates in a pinax/waitinglist/ subfolder in your template search path.


Rendered by list_signup view and gets passed form (WaitingListEntryForm) in context.


Rendered by django.views.generic.TemplateView.


Rendered by survey view when request method is GET and gets passed form (SurveyForm) in context.


Rendered by mail_out_survey_links command and gets passed instance (SurveyInstance instance), site (Site instance) and protocol (DEFAULT_HTTP_PROTOCOL setting).


Rendered by mail_out_survey_links command and gets passed instance (SurveyInstance instance), site (Site instance) and protocol (DEFAULT_HTTP_PROTOCOL setting).


Rendered by django.views.generic.TemplateView after successfully adding user to waiting list.



Triggedered when a user completes a survey through SurveyForm which is used with survey view.

Provides argument form (SurveyForm instance).


Triggered when a user signs up through ajax_list_signup or list_signup views.

Provides argument entry (WaitingListEntry instance).

Change Log


  • Fix render_to_string context_instances kwarg
  • Fix setup.py package_data reference for included templates
  • Add pinax-templates support


  • Update CI configuration
  • Remove docs build support
  • Improve documentation markup


  • Fix setup.py LONG_DESCRIPTION for PyPi


  • Add Django 2.0 compatibility testing
  • Drop Django 1.8, 1.9, 1.10 and Python 3.3 support
  • Convert CI and coverage to CircleCi and CodeCov
  • Add PyPi-compatible long description
  • Move documentation to README.md


  • fixed problem with survey choices in Python 3


  • added campaign tracking
  • added referral tracking


  • added a simple management command to export waitinglist entries


  • fixed paths in mail out email management command


  • don't show empty label in radio choice survey questions


For an overview on how contributing to Pinax works read this blog post and watch the included video, or read our How to Contribute section. For concrete contribution ideas, please see our Ways to Contribute/What We Need Help With section.

In case of any questions we recommend you join our Pinax Slack team and ping us there instead of creating an issue on GitHub. Creating issues on GitHub is of course also valid but we are usually able to help you faster if you ping us in Slack.

We also highly recommend reading our blog post on Open Source and Self-Care.

Code of Conduct

In order to foster a kind, inclusive, and harassment-free community, the Pinax Project has a code of conduct. We ask you to treat everyone as a smart human programmer that shares an interest in Python, Django, and Pinax with you.

Connect with Pinax

For updates and news regarding the Pinax Project, please follow us on Twitter @pinaxproject and check out our Pinax Project blog.


Copyright (c) 2012-2018 James Tauber and contributors under the MIT license.