Adding CAPTCHA and Multiple Login Attempt Limits to Django-Admin
Django's built-in Admin is very useful, but it still feels a bit lacking for production = = Take a look at the Admin introduction: Django follows Python's batteries-included philosophy. It comes with a series of extra, optional tools for solving common problems or needs in web development. These tools and plugins, such as django.contrib.redirects, must be registered in INSTALLED_APPS in settings, and some also require running the manage.py migrate command
目录5 个章节
Django's built-in Admin is very useful, but it still feels a bit lacking for production = =
Take a look at the Admin introduction:
Django follows Python's batteries-included philosophy. It comes with a series of extra, optional tools for solving common problems or needs in web development. These tools and plugins, such as django.contrib.redirects, must be registered in INSTALLED_APPS in settings, and some also require running the manage.py migrate command to create some tables in the database.
The Admin site is the most important thing that sets Django apart from other web frameworks, and it's extremely popular—practically a must-have for going on a trip xxxx. Whether you're writing a small demo or building a large project, you'll find it useful. admin (hereinafter the Admin backend will be referred to as admin) quickly constructs a web site for managing actual data by reading your model data. It's commonly used for development testing, simple management, and similar scenarios, suitable for internal departmental use for work convenience, but it is not recommended for use in production.
Why is it not recommended for production? Because Admin lacks security features like CAPTCHA and login limits! If someone casually brute-forces their way into the backend, how can we guarantee our system's security?
But don't worry—I've already implemented CAPTCHA and login limits by hacking it a bit, so now we can happily use the admin system.
First, take a look at the result

The result looks pretty nice. The number of login attempts can be set yourself; I won't demo it here, since entering the wrong password that many times is too much of a hassle.
CAPTCHA
For the CAPTCHA I used the django-simple-captcha library, together with multi_captcha_admin to generate the CAPTCHA form—very convenient.
First, pip-install these two libraries; everyone knows how, so I won't go into details.
Configure settings.py:
INSTALLED_APPS = [
'multi_captcha_admin',
]
# 验证码配置
MULTI_CAPTCHA_ADMIN = {
'engine': 'simple-captcha',
}
Configure urls.py:
# 添加这一项
path('captcha/', include('captcha.urls')),
That's all it takes. If you're using Django's official Admin, the login CAPTCHA will show up directly. However, I'm using a third-party Admin, so I need to add the form manually.
The method is simple: find login.html and add this item inside the login form.
{{ form.captcha }}
The default generated CAPTCHA and input box use native styles, which look pretty ugly~ We can improve them a bit. I used js to replace the generated image and CAPTCHA input box with elementUI styles. Friends who need this can use it as a reference.
var row = document.querySelector('#captcha_group');
var captcha_img = document.querySelector('img.captcha');
var col_8 = document.createElement('el-col');
col_8.setAttribute(':span', '8');
col_8.appendChild(captcha_img);
var captcha_input = document.querySelector('#id_captcha_1');
var el_input = document.createElement('el-input');
var col_16 = document.createElement('el-col');
col_16.setAttribute(':span', '16');
el_input.setAttribute('name', captcha_input.getAttribute('name'));
el_input.setAttribute('v-model', 'captcha');
el_input.setAttribute('required', 'required');
el_input.setAttribute('placeholder', '请输入验证码');
col_16.appendChild(el_input);
captcha_input.parentNode.removeChild(captcha_input);
row.appendChild(col_8);
row.appendChild(col_16);
Login Rate Limiting
This isn't complicated either, but it still took me quite a while at first—I couldn't find much useful material. Later I went and read Django Admin's source code, and the solution came to me right away haha~
From the admin code, I found that login is handled by the admin.site.login(request, extra_context) method, so the problem becomes very simple: just add a decorator to it. However, we can't modify the framework's code, so we write a new view ourselves, as follows:
# 覆盖默认的admin登录方法实现登录限流
@ratelimit(key='ip', rate='5/m', block=True)
def extend_admin_login(request, extra_context=None):
return admin.site.login(request, extra_context)
Then configure it in urls.py, and remember to put it before admin:
urlpatterns = [
path('admin/login/', views.extend_admin_login),
path('admin/', admin.site.urls),
]
This way you can implement rate limiting. Here I'll introduce the ratelimit decorator, which is provided by the django-ratelimit package. To use this package, you need to configure redis cache. Here's the configuration code:
# 配置redis缓存
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache', # 缓存后端 Redis
# 连接Redis数据库(服务器地址)
# 一主带多从(可以配置个Redis,写走第一台,读走其他的机器)
'LOCATION': [
'redis://localhost:6379/0',
],
'KEY_PREFIX': 'milky', # 项目名当做文件前缀
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient', # 连接选项(默认,不改)
'CONNECTION_POOL_KWARGS': {
'max_connections': 512, # 连接池的连接(最大连接)
},
}
}
}
@ratelimit(key='ip', rate='5/m', block=True), key=ip means distinguishing by IP, rate=5/m means this endpoint can be requested at most 5 times per minute, block=true means requests exceeding this limit are blocked directly. If the block parameter is not set, exceeding the limit won't block, but you can see the request count in the ratelimit counter.
For more usage, see the official docs: https://django-ratelimit.readthedocs.io/en/stable/index.html
References
- https://github.com/a-roomana/django-multi-captcha-admin
- https://django-simple-captcha.readthedocs.io/en/latest/advanced.html#rendering
Feel free to discuss
I've compiled a series of technical articles and materials. Reply with linux, flutter, c#, netcore, android, java, python, etc. in the backend of the WeChat official account 「程序设计实验室」 to get related technical articles and materials. If you have any questions, you can also leave a message in the official account backend~
_EOF_
Adding CAPTCHA and Multiple Login Attempt Limits to Django-Admin
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
聊聊Django应用的部署和性能的那些事儿
前言 随着工作的深入,我越来越发现Python Web开发中有很多坑,也一直在羡慕AspNetCore和Go等的可执行文件部署和高性能,以及Spring生态的丰富,不过因为工作用了Django,生活还是要继续的嘛,这Django好歹也是有很大份额的Web框架,也没那么不堪,至少开发速度上就吊打一众框架了~ 在之前的文章里我介绍过使用Docker部署Django应用的方法,不过那种部署方式只适合上线
2022-05-27 · Django · 约 1 分钟
关于uwsgi服务器的管理
前言 使用Django开发项目好是好,就是部署的时候太麻烦,使用Uwsgi服务器的话,每次修改了代码,都需要重新启动服务器才可以生效。然后uwsgi服务器的重启也挺麻烦。 看了一下官网的文档,最好是把uwsgi安装到venv虚拟环境里面,这样的话在 ps aux 的时候容易区分啦。 查看uwsgi进程 ps -aux | grep uwsgi 结束原uwsgi进程 kill -9 27543 结论
2025-10-27 · Django · 约 1 分钟
Django更换数据库和迁移数据方案
前言 双十一光顾着买东西都没怎么写文章,现在笔记里还有十几篇半成品文章没写完… 今天来分享一下 Django 项目切换数据库和迁移数据的方案,网络上找到的文章方法不一,且使用中容易遇到各类报错,本文根据 Django 官方文档和工作中的经验,稳定可靠,在博客中长期更新~ 如果你遇到同样的问题,阅读本文应该能得到比较好的解决方案。 基本步骤 Django 默认使用 SQLite 数据库方便开发,同时
2022-11-12 · Django · 约 1 分钟
Django:为模板渲染加入Markdown支持
两种方法 Django 的django-markdown-deux模块 Python模块 markdown django-markdown-deux 首先需要安装: pip install django-markdown-deux 修改setting.py 把markdown-deux添加进去 INSTALLED_APPS = [ 'markdown-deux', ] 在模板里添加tags
2022-04-02 · Django · 约 1 分钟
讨论
共 0 条加载评论中…