Day 9 of the Anvil Advent Calendar

Build a web app every day until Christmas, with nothing but Python!

Building a Secret Santa app

You want to exchange Christmas presents at your office, sports club or D&D group, but you don’t want to get presents for everybody. So you set up a Secret Santa – everyone buys a present for someone else, and everyone gets a present. Who bought yours? It’s a secret.

But if you’re the one who picks the match-ups, it’s not a secret any more! What if we could instead get a computer to make the list?

We built a web app to do it, with nothing but Python. (No Javascript, please! I want to enjoy my mulled wine…)

You can use it yourself, right now, at

https://secret-santa.anvil.app

Here’s what it looks like:

Click here to open the source code:

How it works

We built two apps:

  1. An app to organise a Secret Santa group, where you can enter the names and email addresses of everyone who’s taking part.

  2. An app for participating in a Secret Santa group, where you can find out whom you’ve been matched with.

1. Organising the list

The first step is for the organiser to enter the names and email addresses of everyone who’s participating. This is a pretty straightforward multi-user CRUD app (that’s Create/Read/Update/Delete), as seen in our CRUD and multi-user tutorials.

The database looks like this – there is a table of Participants, each linked to the Secret Santa group they’re in (represented by the group_manager – ie the user that set them up). Furthermore, once the present is selected, each participant is linked to the person they’re getting a present_for. In this example, Ian and Meredydd are getting presents for each other:

Note: This guide includes screenshots of the Classic Editor. Since we created this guide, we've released the new Anvil Editor, which is more powerful and easier to use.

All the code in this guide will work, but the Anvil Editor will look a little different to the screenshots you see here!


Choosing Matches

Once the organiser has entered everyone’s details, we need to pick a Secret Santa for everyone in the group! This is trickier than it looks. We initially tried a simple algorithm: for each person, pick a random other person who doesn’t have a gift yet.

But this doesn’t work! For example, consider a three-person group, made up of Alice, Bob and Claire:

If Alice is assigned to Bob, and Bob is assigned to Alice, there is nobody left by the time we get to Claire!

If Alice is assigned to Bob, and Bob is assigned to Alice, there is nobody left by the time we get to Claire!

So, we chose a different algorithm – shuffle and shift. We shuffle the list of participants, using Python’s random.shuffle() function, and then we match each person with the next in the list.

Now we can guarantee that everyone gets a different Secret Santa! Here’s the code to implement it:

  # Shuffle the list of people
  people = list(app_tables.participants.search(group_manager=me))
  random.shuffle(people)
  
  # Assign every person to the next person in the list,
  # wrapping round if necessary
  for i in range(len(people)):
    people[i]['present_for'] = people[i+1] if i+1 < len(people) else people[0]

2. Learning your match

This part is fairly simple – each participant comes in, enters their email address, and is shown whom they’re getting a present for. The only challenge is to prevent peeking – so we make the participant prove ownership of their email address before we tell them anything. They do this by signing up with the Users service – which you can do by clicking on a confirmation email, or by logging in with a Google account.

The “Who is My Secret Santa?” app shares the same Participants table as the organisers’ app. Once the participant has logged in, we show them their assigned partner for every group containing that email address:

Then we show them the result for any group or groups they are part of:

That’s it!

All we need to do is build a pretty front page, and publish it! You can visit the app yourself, at secret-santa.anvil.app:

And you can open the source code to both apps in Anvil by clicking here:


Give the Gift of Python

Share this post: