DeepSeek+Claude强强联手,使用AI驱动DjangoStarter 3.1框架升级

前言

上个月底培训了一周就没时间更新博客

上周有一些空闲时间,就继续体验最近很火的AI辅助编程

之前的文章中有说到我配置好了 VSCode + Cline 插件搭配本地部署的 DeepSeek 来实现AI辅助编程

参考: 开发者新选择:用DeepSeek实现Cursor级智能编程的免费方案

但 Cline 插件消耗 token 太快了,换本地部署的 DeepSeek 的话不够聪明

我后面又换了 RooCode 、 Continue 这俩插件,还有试了一下新的IDE Trae

用下来 RooCode 还不错,这是 Cline 的 fork 版本,功能多了一些,消耗 Token 数量我没去统计,感觉可能差不多

大模型服务我选择了购买 DeepSeek 和 Claude 的 API

Trae 胜在免费,不过国内外区别对待是有点让人难受的

最终我在 Claude 和 DeepSeek 的辅助下,完成了 DjangoStarter 3.1 版本的开发

关于 DjangoStarter

DjangoStarter v3 是下一代 Django 项目快速开发模板,专为提升开发效率和性能而设计。

结合了 Django 的丰富功能和 Django-Ninja 的性能、灵活、简洁特性,v3 版本旨在为开发者提供一个更加强大、简洁和高速的开发体验。

通过这个全新的框架版本,开发者能够迅速搭建起符合现代 web 应用标准的项目基础架构。

之前我写了一篇文章专门介绍这个v3版本,这里就不赘述了。

感兴趣的同学可以查看: 关于正在开发中的DjangoStarter v3版本

重构界面

本次最大的改变就是使用 Tailwind CSS 取代了原本的 Bootstrap,并且加入了很多新的页面,比如用户中心、设置、关于、联系我们、登录、注册、用户协议等,基本就是往 CMS 的方向走。

我甚至一度想引入 wagtail ,不过后面想想还是算了,已经够重了,等下完全和小项目不沾边,哈哈哈😄

国际化支持 (beta)

这次还添加了国际化支持

Django 本身是有国际化功能的

只不过很多项目都去除了

这次我加入了国际化支持,不过只是测试版,只是添加了支持,翻译部分我还没做好,所以也就还没把切换语言的按钮加上。

以下是一些国际化功能的用法

在模板里

django 复制代码
{% translate 'Home' %}

在python代码里

python 复制代码
from django.utils.translation import gettext_lazy as _

print(_('hello'))

生成翻译文件

src 目录下执行

bash 复制代码
django-admin makemessages -l [language_code]

language_code:

  • zh_HAns
  • en_US

其他语言可以参考Django官网

编译消息文件

依然是在 src 目录下执行

bash 复制代码
django-admin compilemessages

Windows 开发环境

如果是使用 windows 开发,需要先安装 gettext 工具

推荐使用 scoop 包管理器

bash 复制代码
scoop install gettext

安装完成之后,执行以下命令验证

bash 复制代码
xgettext --version

部分界面截图

旧版主页

先来看看旧版的主页长什么样

新版主页

新的界面使用 Tailwind CSS 重构,好看了很多

底部也是可以配置的

关于

这个页面做了很多动效,可以看看后面的动图

动效是用AOS做的,感觉还不错,挺方便的,不过要注意得使用 3.0 的 beta 版本,一开始没注意遇到了不少坑。

联系我们

这些联系方式都是可以配置的

表单也用上了 DjangoStarter 新版封装好的 BaseModelForm

封装好的 BaseModelForm 用起来是这样

python 复制代码
class ContactModelForm(BaseModelForm):
    class Meta:
        model = Contact
        fields = ('name', 'email', 'phone', 'message')
        widgets = {
            'name': forms.TextInput(attrs={'placeholder': '请输入您的姓名'}),
            'email': forms.EmailInput(attrs={'placeholder': '请输入您的邮箱'}),
            'phone': forms.TextInput(attrs={'placeholder': '请输入您的联系电话'}),
            'message': forms.Textarea(attrs={'placeholder': '请输入您的留言内容', 'rows': 4})
        }

登录/注册

这个登录页面是之前使用 wagtail 那个项目里面搬过来的

注册页面也是类似的,这里就不贴图片了

个人中心

个人中心这里的布局来自之前的 TodayTV 项目,不过原来也是从其他在线模板参考来的,界面不是很好看。

然而我用 Claude 3.5 和 DeepSeek R1 反复优化多次,仍然无法让我满意,而且代码越来越乱,感觉后面还是得自己来改。

下面的关于我

修改资料

这也是从 TodayTV 项目来的,搭配 Django Forms 实现出来的效果还可以。

隐私政策

这个是用 Claude 生成的,使用 RooCode 优化的提示词,看着有模有样的。

服务条款也是类似的,这里我就不截图了。

Demo页面

为了方便演示各种功能,我还新增了Demo页面

当然这个不太协调的页面是 AI 辅助布局的

错误页面

并且用 Claude 生成了几个错误页面

包括403、404、500页面,都是类似的,这里我只贴403页面的截图

解决了一个 issue

https://github.com/Deali-Axy/DjangoStarter/issues/20

有用户反馈本来应该返回400的接口,实际返回了200

我看了之后发现这个问题属于是从DRF迁移到ninja的历史遗留问题

之前我在框架里封装 responses 用于快捷输出各种返回状态

python 复制代码
def ok(message: str, data: Optional[dict] = None):
    return _gen_resp(message, data, 200)

def forbidden(message: str, data: Optional[dict] = None):
    return _gen_resp(message, data, 403)

def bad_request(message: str, data: Optional[dict] = None):
    return _gen_resp(message, data, 400)

def not_found(message: str, data: Optional[dict] = None):
    return _gen_resp(message, data, 404)

但现在 ninja 里,一直返回的都是 200,这个就是处理返回状态码的地方出问题。

有几种解决思路,反正原本我用重写 renderer 的方式是没办法的,renderer里没法定义返回值,只能改变相应内容。

要不就是用 django 中间件,但需要解析 JSON 会影响性能

最终我对 responses 进行了改造,新增了 ResponseGenerator 这个类,代码就不贴了

关键实现就是用了 ninja 的 api.create_response 这个方法可以指定 status code

在需要用到的地方,比如 src/apps/account/apis/auth/apis.py

python 复制代码
router = Router(tags=['auth'])

_resp = ResponseGenerator(router=router)

@router.post('/register', url_name='account/auth/register')
def register(request, data: RegisterSchema):
    if User.objects.filter(username=data.username).exists():
        return _resp.bad_request(request, '用户名已存在!')

    if data.phone:
        phone_pattern = '^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$'
        if not re.match(phone_pattern, data.phone):
            return _resp.bad_request(request, '手机号码格式不对!')

        if UserProfile.objects.filter(phone=data.phone).exists():
            return _resp.bad_request(request, '手机号已存在!')

    if data.password != data.confirm_password:
        return _resp.bad_request(request, '密码不一致!')

相比起原来的,每个返回的响应需要添加 request 参数

虽然比起原来复杂一点,也算是搞定了。

Todos

  • https://django-ninja.cn 上有不少 ninja 周边生态组件,后续可以用上
  • 将 admin 由 simpleui 切换到 unfold admin
  • 增加更多的默认页面
相关推荐
IVEN_17 小时前
只会Python皮毛?深入理解这几点,轻松进阶全栈开发
python·全栈
Ray Liang18 小时前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
AI攻城狮19 小时前
如何给 AI Agent 做"断舍离":OpenClaw Session 自动清理实践
python
千寻girling19 小时前
一份不可多得的 《 Python 》语言教程
人工智能·后端·python
AI攻城狮1 天前
用 Playwright 实现博客一键发布到稀土掘金
python·自动化运维
曲幽1 天前
FastAPI分布式系统实战:拆解分布式系统中常见问题及解决方案
redis·python·fastapi·web·httpx·lock·asyncio
孟健2 天前
Karpathy 用 200 行纯 Python 从零实现 GPT:代码逐行解析
python
码路飞2 天前
写了个 AI 聊天页面,被 5 种流式格式折腾了一整天 😭
javascript·python
曲幽2 天前
FastAPI压力测试实战:Locust模拟真实用户并发及优化建议
python·fastapi·web·locust·asyncio·test·uvicorn·workers