Pinax

Kaleo: User to User Join Invitations


It's a fairly common feature these days for sites to permit users to invite others to join the site. This is even more popular in closed, private beta sites that haven't launched yet where it is desirable for the user base to grow in an organic but controlled fashion.

Pinax had the beginnings of this functionality going back as far as 0.5 as part of django-friends. One of the goals of Pinax 0.9 has long been to split django-friends into independently usable components, including one for "join invitations" separate from any notion of friendship. The original version in django-friends, however, was ill-suited to sites in private-beta where it needs to interact with signup_codes and provide support for each user having a limited number of invitations to hand out.

So as part of re-implementing the join invitation functionality for KodeNode, we decided to pull the code out in a reusable app for Pinax named kaleo (pronounced kah-leh'-oh) which is Ancient Greek for "call or invite".

Installing Kaleo

In order to install kaleo, simple use pip:

pip install kaleo

or better, add

kaleo==0.2

to your project's requirements file.

Adding to Project

Adding it to your site is quick and easy:

# settings.py
INSTALLED_APPS = [
    ...
    "kaleo",
    ...
]

# urls.py
urlpatterns = patterns("",
    ...
    url(r"^invites/", include("kaleo.urls")),
    ...
)

Now that technically adds it to your project but you'll need to display the form somewhere. Also, you can optionally expose the number of invites left for a user, as well as display the list of invitees for the particular user who has already invited people.

To display the form:

{% load kaleo_tags %}

<div class="invites">
    {% invite_form request.user %}
</div>

The form posts to a view that expects AJAX and returns JSON, so you'll want a bit of Javascript somewhere like this:

$(function () {
    $('.invites form').ajaxForm(function(data) {
        if (data.status == "OK") {
            $('#invitation-form-messages').html("<p>Invitation sent to " + data.email + "</p>");
            $('.empty-invites').remove();
            $('.invite-list').append("<li>" + data.email + "</li>");
            $('.invites form input[type=text]').val("");
            $('.invitations_remaining').html("(" + data.invitations_remaining + ")");
            if (data.invitations_remaining == 0) {
                $('.invitation_form form').hide();
            }
        } else {
            $('#invitation-form-messages').html(data.errors);
        }
    });
});

The .empty-invites and .invite-list are divs defined in the included kaleo/_invited.html template.

To display the invitees:

{% load kaleo_tags %}

<div class="invites">
    <div class="sent">
        <h3>Invitations Sent</h3>
        {% invites_sent request.user %}
    </div>
</div>

Lastly, if you want to display a count of remaining invites to your users:

{% load kaleo_tags %}
    
<span class="invitations_remaining">
    ({% remaining_invites user %})
</span>

Management Commands

By default, users will not start with any invitations. You'll obviously want to fix this, or else what was the point of installing kaleo? There are two management commands that serve overlapping purposes.

add_invites

When you run add_invites, you pass it a single parameter that must be an integer:

python manage.py add_invites 10

This will add 10 invites to every user that has 0 invites remaining.

topoff_invites

When you run topoff_invites, you pass it a single paramter that also must be an integer:

python manage.py topoff_invites 10

This will make sure that every user has at least 10 invites remaining.

Settings

KALEO_DEFAULT_EXPIRATION

This defines how long invitations are valid. By default it will last 168 hours, or 7 days.

KALEO_DEFAULT_INVITE_ALLOCATION

This defines how many invites new users will be allocated. It defaults to 0.

Documentation

Documentation for this project is kept up to date on Read The Docs.

Code

The repository can be found http://github.com/eldarion/kaleo.

Final Thoughts

This app is designed to make it quick and easy to add a user to user join invitation feature to your new or existing Pinax site, whether it is open signup or closed private beta.