尝试

在一个平常的工作日下午,小琪在她的工位上尝试着刚刚发现的一个新工具——nanodjango​。她觉得这个工具看起来挺有趣的,想要看看它是不是真的能让开发变得更简单。

小胖那天提前完成了手头的任务,走到小琪的工位旁边,看到她在屏幕上捣鼓着什么。“嘿,小琪,你在忙什么呢?”小胖好奇地问道。

“哦,小胖,来看看这个,”小琪说,“我刚发现了个叫 nanodjango​ 的东西,可以在一个文件里完成整个 Django 应用,感觉挺有意思的。”

小胖凑近了一点,看了一眼屏幕上的代码,然后笑着说:“哇,你这个django正不正宗,怎么看起来像flask?”

小琪笑了笑回答:“是啊,但它其实是基于 Django 的,只是更简化了。你看,我已经写了一个简单的计数器应用,它还能直接跑起来。”说着,小琪展示了她写的代码:

from django.db import models
from nanodjango import Django

app = Django()

@app.admin
class CountLog(models.Model):
    # 标准 Django 模型,注册到管理后台
    timestamp = models.DateTimeField(auto_now_add=True)

@app.route("/")
def count(request):
    # 标准 Django 函数视图
    CountLog.objects.create()
    return f"<p>Number of page loads: {CountLog.objects.count()}</p>"

“真酷!”小胖点头说,“不过这样会不会少了点什么?我们平时都习惯用 manage.py 和那些标准命令了。”

“刚开始我也这么想,”小琪解释道,“但其实它支持很多 Django 的特性,比如模型、视图和管理后台。而且,如果你的应用变大了,还能轻松转换成完整的 Django 项目。”

“那确实不错。”小胖表示赞同,“你这个计数器怎么工作的?”

小琪给小胖演示了一下如何通过访问主页增加计数,以及如何通过 API 获取当前计数,并补充了API端点的代码:

@app.api.get("/add")
def add(request, a: int, b: int):
    # Django Ninja API 支持内置
    CountLog.objects.create()
    return {"count": CountLog.objects.count(), "sum": a + b}

“有意思,”小胖眼睛一亮,“我应该怎么开始使用它呢?”

小琪指着屏幕上的注释说道:“首先,我们需要安装 nanodjango​。你可以用 pip 来安装它,就像这样:”

pip install nanodjango

小胖立刻在自己的终端上运行了这条命令,几秒钟后安装完成。“太棒了,接下来呢?”

“接下来就是编写我们的应用代码,”小琪说,“我已经写好了大部分内容。最后一步是保存这个文件,比如命名为 counter.py​,然后我们可以用下面的命令来启动它:”

nanodjango run counter.py

小胖照做了,果然,一个本地服务器成功启动,他可以通过浏览器访问页面并测试计数功能,同时还执行了django默认的migrations,默认使用的是sqlite数据库。

“如果我想让它支持异步请求怎么办?”小胖突然想到一个问题。

小琪微笑着回应:“nanodjango​ 也支持异步视图,看这里:”

@app.route("/slow/")
async def slow(request):
    import asyncio
    await asyncio.sleep(10)
    return "Async views supported"

接着,小琪继续介绍 nanodjango​ 对 API 的支持:“你知道吗?nanodjango​ 内置了对 Django Ninja 的支持,使得构建 RESTful API 更加容易。例如,我们可以定义一个简单的 API 端点如下:”

from ninja import Schema

class Item(Schema):
    foo: str
    bar: float

@app.api.post('/do_something')
def do_something(
    request,
    item: Item,
    file: app.ninja.UploadedFile = app.ninja.File(...)
):
    # 处理上传的文件和数据
    return {"message": "Processing completed"}

小胖点了点头,表示理解:“这看起来很方便,特别是当我们需要快速搭建一些原型或小型应用时。”

小琪又提到:“对于更复杂的 API,我们可以直接使用 app.ninja​ 属性来访问额外的功能,而不需要直接导入 Django Ninja。这是为了避免某些导入顺序的问题。”

小胖对此感到好奇:“为什么不能直接导入 Django Ninja 呢?”

“这是因为 ninja​ 模块在导入时会尝试访问 Django 设置,而在 nanodjango​ 中所有配置都是在一个文件里完成的。如果我们先初始化 Django()​,然后再导入 ninja​,就不会有问题了。但是为了保持代码整洁,推荐使用 app.ninja​ 这个辅助属性。”

小胖若有所思地点点头,明白了其中的道理。

管理后台

“说到管理后台,”小琪继续道,“在 nanodjango​ 中,只要我们用 @app.admin​ 装饰器装饰模型,或者在设置中指定 ADMIN_URL​,管理后台就会自动启用。”

她展示了如何注册一个模型到管理后台:

@app.admin(list_display=["id", "timestamp"], readonly_fields=["timestamp"])
class CountLog(models.Model):
    timestamp = models.DateTimeField(auto_now_add=True)

“如果模型比较复杂,我们也可以按照标准的 Django 方式注册自定义的 ModelAdmin​ 类。”小琪补充道。

from django.contrib import admin

class CountLogAdmin(admin.ModelAdmin):
    list_display = ["id", "timestamp"]
    readonly_fields = ["timestamp"]

admin.site.register(CountLog, CountLogAdmin)

两人聊得越来越起劲,开始讨论起可以使用 nanodjango​ 来改进哪些工作流程,甚至设想了一些新的项目想法。他们还一起探讨了如何将这个工具集成到他们的日常工作中,比如创建内部使用的统计页面或自动化测试环境。

结尾

几天后,小胖和小琪利用 nanodjango​ 完成了一个小工具,并向团队展示了它的潜力。此外,当他们需要将项目从单文件转换为完整的 Django 项目时,只需使用以下命令:

nanodjango convert counter.py path/to/site --name=counter

这使得他们的应用能够随着业务需求的增长而扩展,保持灵活性的同时不失稳定性。

https://github.com/radiac/nanodjango

欢迎大家关注我的公众号~

Snipaste_2024-12-07_11-05-00.png