• 关于正在开发中的DjangoStarter v3版本


    前言#

    最近做的这个项目大量使用了 python 及其相关的生态,因此自然而然选择了我的 DjangoStarter 作为后端框架

    之前 v2 版本是用 RestFramework 做接口的,后面我试用了一次 django-ninja 之后就喜欢这种类似 FastApi 的写接口方式

    正所谓天下苦 drf 久矣,在新的 v3 版本框架中,我决定直接把整个 RestFramework 替换成 ninja

    目前大部分功能都完成了,代码在主项目的 v3-alpha 分支里,等开发完成我会合并到 master 里 (现在基本可用了)

    另外还做了很多新功能和改进,接下来会介绍一下

    关于 DjangoStarter#

    这个开发脚手架,最开始还是叫 DjangoRails ,名字模仿的 Ruby on Rails

    后面经过重构才改成 DjangoStarter

    这个脚手架起源于2020年开始的项目,当时使用 Django + RestFramework 作为后端框架,为了满足安全部门的要求,又做了很多魔改,再加上其他一些配置啥的,慢慢的就积累出了 DjangoStarter ~

    这里贴一下项目介绍吧~

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

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

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

    核心特性#

    • Django Ninja 集成:采用 Django Ninja 替代传统的 Django Rest Framework,为 API 开发带来了性能优化和更简洁的编码体验。利用 Python 类型提示,自动生成交互式 API 文档,不再需要 drf-yasg 那一堆繁琐的手动配置文档,同时提升了代码的可读性和维护性。
    • 增强的安全性:内置了多项安全功能,包括但不限于 Admin 登录验证码、IP 限制等,确保应用的安全性。
    • 代码自动生成:v3 版本进一步优化了代码生成器,丢掉了 DRF 这个包袱,只需要定义模型,就可以生成 schema 以及 RESTFul API,还能根据定义自动创建测试用例,大大提高开发效率。
    • 随机种子数据生成:v3 版本内置 seed 模块,支持为已有模型自动填充假数据,方便开发测试。
    • 模块化项目结构:推出了更加模块化的项目结构设计,方便开发者根据需要添加或移除功能模块,使项目维护更为简单。
    • 现代化前端集成:提供了对现代化前端技术的集成,以及利用 NPM 和 gulp 管理前端资源,帮助开发者打造富交互式的用户界面。
    • 容器化支持:内置 Dockerfile 和 docker-compose.yml 配置,简化了容器化部署的过程,支持一键部署到任何支持 Docker 的环境。
    • 详尽的文档与社区生态:提供全面的文档和指南,覆盖从项目启动到部署的每一个步骤。同时,基于活跃的 Django 开源社区,开发者可以轻松获取支持和反馈。

    关于v3版本#

    OK,终于说回正题

    这次重构v3版本最主要的原因是把 RestFramework 替换成 ninja

    然后也做了一些新的功能

    比如:

    • 新的自动代码生成功能
    • 完善了单元测试和集成测试,搭配代码生成,可以为每个应用自动生成 crud 的测试用例
    • 随机种子数据,目前使用 faker 实现假数据,打算进一步实现类似 EFCore 的种子数据机制,使假数据更自然
    • 新的登录接口
    • 多种第三方登录接入(目前接了微信、小程序、企微)
    • 使用 tailwindcss 替换 bootstrap 实现前端(只是一些简单的后台展示,还是以 API 为主)
    • 拆分 settings 配置,像 AspNetCore 那样支持多个环境配置
    • 更换了包管理器

    目前大概就这些吧

    后面有用到什么新的再一步步加入

    代码生成#

    一直没有好好介绍一下 DjangoStarter 框架的具体实现

    代码生成这块其实也不复杂,包名是 django_starter.contrib.code_generator

    主要就两个部分

    • 分析器 - src/django_starter/contrib/code_generator/analyzer.py
    • 生成器 - src/django_starter/contrib/code_generator/generator.py

    分析器使用 django.apps.apps 提供的 get_app_configget_models 来扫描已注册的所有 App

    然后搭配反射(或者在 Python 中应该叫自省 inspect)来获取各个字段的信息,把搜集到的信息保存到我定义的几个对象中

    然后在生成器部分,根据特定的规则,使用 jinja2 模板进行渲染~

    注意要把字段的 primary_key, is_relation 这些属性拿出来,后面有用。如果是关系字段(如外键)的话,还需要把 target_field 拿出来。

    大概思路就是这样,其中有很多细节的地方,本文的篇幅受限,后续我写篇文章来介绍吧。

    API#

    使用 ninja 来写 API

    不同于之前的 RestFramework ,ninja 用的是装饰器来定义路径,这个对于不喜欢 Django 配置式路由的人来说很友好

    项目结构我也做了一些调整

    以 demo 应用为例

    每个 model 都在 apis 下单独创建一个 package,单独有 apis.py 和 schemas.py 代码,这样不会把所有代码逻辑混在一起

    PS:后续如果我转向使用 FastApi,也可以用这个思路来组织项目

     demo
     ├─ tests
     │  ├─ __init__.py
     │  ├─ test_music_album.py
     │  ├─ test_music.py
     │  ├─ test_movie.py
     │  └─ test_actor.py
     ├─ migrations
     │  ├─ __init__.py
     │  └─ 0001_initial.py
     ├─ apis
     │  ├─ music_album
     │  │  ├─ __init__.py
     │  │  ├─ schemas.py
     │  │  └─ apis.py
     │  ├─ music
     │  │  ├─ __init__.py
     │  │  ├─ schemas.py
     │  │  └─ apis.py
     │  ├─ movie
     │  │  ├─ __init__.py
     │  │  ├─ schemas.py
     │  │  └─ apis.py
     │  ├─ actor
     │  │  ├─ __init__.py
     │  │  ├─ schemas.py
     │  │  └─ apis.py
     │  └─ __init__.py
     ├─ __init__.py
     ├─ views.py
     ├─ models.py
     ├─ apps.py
     └─ admin.py
    

    坑点#

    要说的话,ninja 这种比较新的库,还是有一点点坑的地方的

    • 有些文档不够详细
    • URL reverse 功能不够好用,只能在 NinjaAPI 对象配置 urls_namespace ,下面的各级 router 都不能配置 urls_namespace,我只能对下面的接口用 url_name='demo/movie/list' 这种形式的命名
    • ModelSchema 对外键的支持有限,对于输入的 schema ,不能在 Meta.fields 里配置这个外键字段,需要自己单独写出来,这点对于自动生成代码来说有点麻烦,不过我已经解决了

    种子数据/假数据#

    这个可以叫 seed data ,也可以叫 mock data

    在开发测试中很有用,不用手动去添加各种数据

    包名是 django_starter.contrib.seed

    一开始我是找到了一个叫 django-seed 的库,可以实现种子数据的生成

    不过这个包已经年久失修,好几年没更新了

    我试了一下,运行起来居然还依赖 PostgreSql 的库?!

    就离谱,不应该和数据库无关的吗……

    算了,我自己写得了,又不难

    Python 生态就是好,Faker 库用来生成随机假数据很好用

    主要代码在 src/django_starter/contrib/seed/seeder.py 文件里

    就是根据不同的字段类型,使用不同的假数据方法

    坑点:外键#

    其中外键字段会比较坑,需要做一些特殊处理

    related_model = field.related_model
    # Ensure there is at least one instance of the related model
    related_instance = related_model.objects.order_by('?').first()
    if not related_instance:
      related_instance = related_model.objects.create(**self.seed(related_model))
    # Set the foreign key ID field
    fake_data[field.attname] = related_instance.pk
    

    settings 拆分#

    早就对 Django 的配置 settings.py 不爽了

    项目一大,这个文件就乱七八糟又臭又长

    而且还不支持多环境切换,得自己写一堆逻辑去判断不同环境

    之前版本中,我是把几个主要的配置拆分成不同文件,然后在 settings.py 里引用

    现在我用上了 django-split-settings 这个包,瞬间舒服了

    来看看现在的 config 目录

     config
     ├─ settings
     │  ├─ environments
     │  │  ├─ __init__.py
     │  │  ├─ testing.py
     │  │  ├─ production.py
     │  │  ├─ local.py.template
     │  │  └─ development.py
     │  ├─ components
     │  │  ├─ __init__.py
     │  │  ├─ simpleui.py
     │  │  ├─ rq.py
     │  │  ├─ ninja.py
     │  │  ├─ logging.py
     │  │  ├─ django_starter.py
     │  │  ├─ database.py
     │  │  ├─ csp.py
     │  │  ├─ cors.py
     │  │  ├─ common.py
     │  │  ├─ captcha.py
     │  │  └─ caches.py
     │  └─ __init__.py
     ├─ __init__.py
     ├─ wsgi.py
     ├─ urls_root.py
     ├─ urls.py
     ├─ env_init.py
     ├─ asgi.py
     └─ apis.py
    

    可以看到现在 settings 变成了一个 package

    各种配置拆分出来分散到 components 下面

    然后不同的环境又放到 environments 下面,可以覆盖前面定义的配置

    很好的解决了之前的几个痛点

    更换包管理器#

    原本就直接使用 pip ,搭配 requirements.txt 来管理依赖

    这个方式的优缺点我就不多说了

    这次换成 pdm ,总算有点现代包管理器的感觉了

    PS:其实我之前还用过 poetry ,不过偶尔会遇到一些奇奇怪怪的问题,弃了~

    小结#

    大概就这些吧,后面有什么新的想法我再来更新

    还有其中几个关键的更新我可能会单独写文章来详细介绍~

    作者:DealiAxy

    出处:https://www.cnblogs.com/deali/p/18237621

    版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

    微信公众号:「程序设计实验室」
    新版StarBlog已经上线,地址:http://blog.deali.cn

  • 相关阅读:
    golang singleflight资料整理
    Android kotlin自定义圆形菜单的功能实现
    主要开源WebGIS介绍、自由及开源GIS软件、组件产品
    [python] pytest
    基于ResNetRS的宝可梦图像识别
    【C#】WPF获取屏幕分辨率
    【生成式网络】入门篇(二):GAN的 代码和结果记录
    分类模型的Top 1和Top 5
    试从多个方面比较电路交换、报文交换和分组交换的主要优缺点?
    python -opencv 中值滤波 ,均值滤波,高斯滤波实战
  • 原文地址:https://www.cnblogs.com/deali/p/18237621