How to elegantly generate unique IDs in a Django project?
When it comes to generating unique IDs, Django isn't much different from other backend frameworks—the thinking is similar, except you can cut corners a bit by leveraging the Python ecosystem…
目录12 个章节
Introduction
Originally, the title was intended to be "Generating Non-Repetitive Four-Digit Numbers," but since numbers alone are somewhat limiting, it's been generalized to non-repetitive IDs.
This feature was encountered while working on the small project shown in the image below, which is somewhat similar to WeChat's "Face-to-Face Group Creation." It generates a random and unique password, and others can join the classroom by entering this password.

There are several ways to implement this feature, and this article will briefly document one approach.
Without Relying on Third-Party Libraries
First, let's implement this function purely based on Django ORM.
First, define a model.
from django.db import models
class MyModel(models.Model):
unique_code = models.CharField(max_length=4, unique=True)
Single Task
The simplest and most straightforward method is to write an infinite loop.
import random
def generate_unique_code():
while True:
code = str(random.randint(1000, 9999))
if not MyModel.objects.filter(unique_code=code).exists():
return code
This implementation is definitely reliable in a single-threaded testing environment. However, this operation is not atomic, and in a concurrent environment, it may generate duplicate numbers.
Considering Concurrency
In high-concurrency scenarios, you can use database transactions or optimistic locking.
from django.db import transaction, IntegrityError
def create_instance():
# Number of attempts
retry = 10
for _ in range(retry):
code = generate_unique_code()
try:
with transaction.atomic():
instance = MyModel(unique_code=code)
instance.save()
return instance
except IntegrityError:
# If a uniqueness conflict occurs, retry
continue
raise Exception("Unable to generate a unique four-digit number")
Pre-generating
The first two methods require frequent database reads, resulting in relatively poor performance.
Alternatively, we can trade space for time. Since it's only four-digit numbers, the range from 0000 to 9999 doesn't contain too many values. We can pre-save these ten thousand rows into the database and add an available field.
When we need to generate a unique ID, we first filter for data where available == True, then randomly select one; and set this field to False.
This is the general idea.
Using Third-Party Libraries
In this project, I used these three libraries together (this is also the main purpose of writing this article, to document these libraries)
- shortuuid
- hashids
- django-autoslug
shortuuid
shortuuid is a lightweight library for generating shorter UUIDs.
Implementing this functionality using this library is straightforward.
import shortuuid
shortuuid.ShortUUID(alphabet="0123456789").random(length=4)
However, in this project, I did not use this library for this purpose.
In fact, as the name suggests, this library has "uuid" in it and is naturally used for tasks related to Python's built-in UUID.
I used this library to simplify the ID of the Client model to 7 characters.
class Client(ModelExt):
client_id = models.UUIDField(default=uuid.uuid4, editable=False)
client_key = models.CharField(max_length=100, default=uuid.uuid4)
user = models.OneToOneField(
User, on_delete=models.SET_NULL, db_constraint=False, null=True, blank=True, unique=True,
)
consumer_name = models.CharField(max_length=100, null=True, blank=True)
is_online = models.BooleanField(default=False)
def short_client_id(self):
short = shortuuid.encode(self.client_id)
return short[:7]
The shortuuid.encode method can convert a 32-character UUID into 22 characters, and it can be restored using the decode method.
hashids
This is a library for converting numbers into short strings
Although the name includes "hash," the encoding of this library is reversible
import hashids
h = hashids.Hashids()
h.encode(123, 456)
Out[15]: 'X68fkp'
h.decode('X68fkp')
Out[16]: (123, 456)
I used it to generate classroom names based on timestamps
```python
def get_timestamp_hashid():
hashids = Hashids(salt='hahaha salt lala')
t = timezone.now().timestamp()
result = tuple(map(int, str(t).split('.')))
return hashids.encode(*result)
Because the encode method accepts numbers (or a tuple containing numbers), here the integer and decimal parts of the timestamp are converted into a tuple and then passed into hashids
django-autoslug
This library is used to generate unique slugs based on fields, and it also allows for custom generation logic.
I used this library to implement the unique classroom password generation feature (but I wouldn't particularly recommend this approach).
from autoslug import AutoSlugField
def populate_classroom_number(instance):
return str(random.randint(1000, 9999))
class ClassroomIdiom(ModelExt):
name = models.CharField(max_length=100)
number = AutoSlugField(populate_from=populate_classroom_number, unique=True)
The principle behind this library is straightforward. It generates a slug based on user-defined rules, then checks the database for duplicates. If a duplicate is found, it appends a number to the end. This process can potentially result in numbers that exceed four digits.
The best approach is still the third method I mentioned earlier, which does not rely on any third-party libraries.
Using django-autoslug here was simply for convenience, delegating the complex logic to a third-party library. After all, this is just a toy project.
Summary
When it comes to generating unique IDs, Django isn't really different from other backend frameworks—the approach is quite similar. It's just that you can take advantage of the Python ecosystem to cut some corners...
_EOF_
How to elegantly generate unique IDs in a Django project?
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
实测 Django 6.0:模版片段、后台任务、CSP 安全,三大特性体验报告
呵,连WebSocket都没塞进去就敢叫大版本更新?不过模版片段和内置后台任务总算让Django像个现代框架了,至少写HTMX时不用再到处塞碎片文件。原生CSP?早该有了。至于抛弃Python 3.11——跟不上时代的版本留着也是累赘。
2026-01-20 · Django · 约 1 分钟
Django全文检索实现:HayStack-+-Whoosh-+-Jieba
涉及到的工具 haystack是django的开源搜索框架,该框架支持**Solr**, Elasticsearch, Whoosh, **Xapian搜索引擎,不用更改代码,直接切换引擎,减少代码量。 搜索引擎使用Whoosh,这是一个由纯Python实现的全文搜索引擎,没有二进制文件等,比较小巧,配置比较简单,当然性能自然略低。 中文分词Jieba,由于Whoosh自带的是英文分词,对中文的分
2022-08-26 · Django · 约 1 分钟
Django项目引入NPM和gulp管理前端资源
前言 之前写了一篇《Asp-Net-Core开发笔记:使用NPM和gulp管理前端静态文件》,现在又来用Django开发项目了,之前我搞了一个Django的快速开发脚手架「DjangoStarter」,正好给升级一下~ 关于npm和gulp我就不多重复了,之前那篇文章都写了,直接上操作 安装依赖 安装依赖的操作跟上一篇文章是一样的,不过我这里直接提供package.json文件,复制到项目根目录里
2022-04-02 · Django · 约 1 分钟
Django中「强行」使用MVVM设计模式
扫盲 首先带大家了解一下什么是MVVM模式: 什么是MVVM?MVVM是Model-View-ViewModel的缩写。 MVVM是MVC的增强版,实质上和MVC没有本质区别,只是代码的位置变动而已 从名字上看,MVVM比MVC架构中多了一个ViewModel,没错,就是这个ViewModel,他是MVVM相对于MVC改进的核心思想。在开发过程中,由于需求的变更或添加,项目的复杂度越来越高,代码量
2021-12-18 · Django · 约 1 分钟
讨论
共 0 条加载评论中…