Generating unique names
MP 165: TIL about secrets.token_hex().
I've been working on dsd-scalingo recently, a django-simple-deploy plugin that automates the process of deploying Django projects to Scalingo. I'm excited about this work, because Scalingo seems to be one of the best platforms available at the moment for teaching people how to deploy their Django projects.
I ran into an issue with choosing names for users' projects. Most platforms have some kind of uniqueness constraints for project names. Some platforms require that every project an individual user deploys must have a unique name. But some platforms, like Scalingo, require that all project names across the entire platform have a unique name.
This is easy to address, but when I was implementing this change I discovered a simpler way to generate unique names, using the secrets module.
Scalingo's fair, effective free trial policy
I'm excited about making it easier for Django developers to deploy to Scalingo for two reasons. I like how their deployments are structured, and they have a thoughtful and effective free trial policy.
Scalingo's free trial lasts 30 days. That's plenty of time to see if you like their platform, but not so long that they'll run into a bunch of exploitative and abusive behavior by users on the free trial. This is much nicer than the 7-14 day trials I see on most other platforms. For people who know what they're looking for in a hosting platform, shorter trials can work. But for people who are sorting all this out for the first time, it's easy to have the trial end before they've had a chance to really evaluate the platform.
Also, Scalingo doesn't require a credit card to sign up for the free trial. That's incredibly helpful for people who are on a tight budget. There are many people who want to learn deployment, but can't risk ending up with a ~$20/month charge because they forgot to fully destroy the project they were practicing with. Users like this absolutely can't handle accidentally accruing even higher charges, because they provisioned too many resources, or the wrong kinds of resources. Allowing people to try a platform without requiring a credit card is the only way to truly offer a "risk-free" trial.
Generating unique names: the long way
When users install dsd-scalingo and then run python manage.py deploy --automate-all, the plugin has to create a Scalingo app for the user. That means the plugin needs to choose a name for the deployed project. We know the user's local project name, for example blog. But we need to make that name unique; we want something like blog-020f47a5.
I used to generate unique names like this:
import random import string name = "blog" characters = string.ascii_lowercase + string.digits token = "".join(random.choices(characters, k=8)) deployed_name = f"{name}-{token}" print(deployed_name)
This block defines a set of allowed characters, which includes all ascii lowercase letters and all ten digits (0-9). It then makes eight random choices from that set of characters, and joins them with an empty string. The value of deployed_name is the original name, with a hyphen and the random token:
blog-5fe1zxl6
I learned that approach a long time ago, and have used it in a number of projects over the years.
Generating unique names: the short way
When I needed to generate unique names for the Scalingo plugin, I decided to take a moment and see if there's a simpler way to generate these tokens. There is!
import secrets name = "blog" deployed_name = f"{name}-{secrets.token_hex(4)}" print(deployed_name)
The secrets.token_hex() function takes in a length in bytes, and returns a random string made up of hexadecimal characters:
blog-2bcba64f
This doesn't draw from the same set of characters; the hexadecimal set it draws from are the digits 0-9, and the letters a-f. But that's plenty of characters to get a token that's unique enough for generating an appropriate project name on a platform like Scalingo. If it ever proves to not be unique enough, I can extend the length of the token, or choose a function that includes additional characters.

ll-project-0ad21f25.Conclusions
I had heard of the secrets module before, but had never taken much notice of it because random has always been enough for my needs. I didn't need cryptographically secure functions for today's work, but I'm glad I took a look at the secrets module. It provides a simpler implementation than what I've been using for generating unique names.