This project provides a neat way to engage beta users into completing custom-defined beta-testing tasks, and getting assigned a "badge" after completion of such a task. It also comes with a way to track the path users took when trying to complete a task, and a feedback button on the side of the page that they can use to send feedback at any point.
The project is based on a number of other projects, and combines them all into one package that can be switched on for the beta period, and switched off again afterwards. Some of the packages used in this are:
This is itself still very much beta software, so feel free to submit additions, fixes or bug reports!
How to install
Put the "betatest" directory somewhere in your python path
Add "badges" to your installed apps (in the settings.py file)
OPTIONAL: If you want to use the pre-made badges overview/checklist page, add this to your main "urls.py" file:
- urlpatterns += patterns('',
How to make badges
Create a "meta_badges.py" file and import it at the bottom of your models.py file. This is where you will define all badge classes. Every badge is subclassed from "badges.MetaBadge"
Here is an example badge that is awarded to users who fill in all the fields on their profile:
import badges from myapp.models import UserProfile
- class Autobiographer(badges.MetaBadge):
id = "autobiographer" model = UserProfile one_time_only = True
title = "Autobiographer" description = "Completed the User Profile" level = "1"
progress_start = 0 progress_finish = 2
- def get_user(self, instance):
- return instance.user
- def get_progress(self, user):
- has_email = 1 if user.email else 0 has_bio = 1 if user.get_profile().bio else 0 return has_email + has_bio
- def check_email(self, instance):
- return instance.user.email
- def check_bio(self, instance):
- return instance.bio
The badges are awarded using the post_save signal. So whenever a member of the model, in this case "UserProfile," is saved, it checks to see if the user should be awarded a badge.
In this example, whenever a user profile is saved, the badges app checks each of the conditions and if they are all True, then the badge is awarded.
The "get_user" method is passed the same instance as the condition checks and needs to return the user who should receive the badge. The default is instance.user
The "one_time_only" attribute determines whether a user can earn the badge more than once. If a badge was awarded for writing a post that got 1000 views, you may want to award it for EACH post that gets 1000 views, instead of just the first time.
Conditions are callback functions. Any methods of your badge class whose names start with "check" will be passed an instance of the model instance that has just been saved. If all the conditions return "True," the badge will be awarded (unless it's a one-time-only and the user already has it).
Progress Reporting (optional) ===
If you would like to display a progress bar to your users, set the progress_start, and progress_end, attributes and define the get_progress() function as seen in the example above.
By default, progress_start is 0, and progress_end is 1. The default get_progress() returns 0 if the user has not yet earned the badge and 1 if they have (so it jumps from 0% to 100% when they earn the badge)
You can get the percent completion of a badge for a given user like so:
>>> user = User.objects.create(username='tester', email@example.com') >>> badge = Badge.objects.get(id='autobiographer')>>> badge.meta_badge.get_progress(user) ... 1>>> badge.meta_badge.get_progress_percentage(user=user) ... 50.0>>> profile = user.get_profile() >>> profile.bio = "hello, world!" >>> profile.save()>>> badge.meta_badge.get_progress(user) ... 2>>> badge.meta_badge.get_progress_percentage(user=user) ... 100.0
### Badge Attributes
There are some badge info attributes which define the information about the badge that will be shown on your website:
#### id the unique name that will be used to identify the badge in your database. The reason for this is so that you can change the title, description, and level without worry
#### title the Name of the badge as it will appear on the website.
#### description a short description of the badge as it will appear on the website.
#### level badges are either easy (bronze/b), medium (silver/s), or hard (gold/g) to get. It would not be very hard to change the levels to something else like numbers.
#### progress_start (optional | default == 0) Indicates the value get_progress() should return when the user has not made any progress on this badge.
#### progress_end (optional | default == 1) Indicates the value get_progress() should return when the user has earned the badge. Note that if get_progress() returns a value larger than progress_end for a given user, get_progress_percentage() will still only return 100.0 (ie. 100%)
When a badge is awarded, a signal is fired (found in badges.signals). The "sender" keyword argument is the metaBadge you defined (Autobiographer in this case), and NOT the badge model instance that is automatically created. The "user" keyword argument is the user who the badge was awarded to, and the "badge" keyword argument is the model instance of the badge in the database (badges.models.Badge)
from badges.signals import badge_awarded
- def do_something_after_badge_is_awarded(sender, user, badge):
Manually Awarding a Badge
You can manually award a badge to a user using the "award_to" method on the Badge model instance.
Example: Award a random badge to a random user...
from django.contrib.auth.models import User from badges.models import Badge
random_user = User.objects.order_by("?") random_badge = Badges.objects.order_by("?")