Django视图进阶:快捷函数、装饰器与请求响应

在上一篇文章中欧,我们学习了Django视图与路由的基础流程 ------ 通过路由映射请求到视图,用视图函数处理简单逻辑并返回响应。但在实际开发中,我们还需要更高效的工具(如快捷函数)、更灵活的功能扩展(如视图装饰器),以及处理复杂场景(如JSON响应。文件上传)。本篇文章将聚焦这些进阶能力,带你提示Django视图开发的效率与灵活性

一、快捷函数:简化视图开发

Django的 django.shortcuts 模块提供了一组快捷函数,封装了视图开发中常用的重复逻辑(如渲染模板、查询数据、重定向),让你用更少的代码实现更多功能

1.1 render():渲染模版并返回响应

最常用的快捷函数,用于将模板与上下文数据结合,生成 HttpResponse 对象,无需手动创建 HttpResponse ,也无需指定模版路径(Django 会自动在templates 目录下查找)

语法:

python 复制代码
render(request, template_name, context=None, content_type=None, status=None, using=None)

①request:Http请求对象(必须传) ②template_name:模版文件名(必须传)

③context:传递给模版的上下文字典(键为模版变量名,值为数据) ④status:Http状态码

举例:

python 复制代码
# myapp/views.py
from django.shortcuts import render
from .models import Article

def article_detail(request, pk):
    """用render()渲染文章详情模板"""
    article = Article.objects.get(pk=pk)
    # 上下文字典:模板中可通过{{ article.title }}访问数据
    context = {
        'article': article,
        'author': article.author.username,  # 关联数据
        'is_favorite': request.user.is_authenticated  # 业务逻辑判断
    }
    # 渲染模板并返回响应(无需手动创建HttpResponse)
    return render(request, 'article_detail.html', context)

在模版中使用上下文:

html 复制代码
<!-- article_detail.html -->
<h1>{{ article.title }}</h1>
<p>作者:{{ author }}</p>
{% if is_favorite %}
    <button>添加收藏</button>
{% endif %}
<div>{{ article.content }}</div>

1.2 redirect():重定向到其他URL

用于实现页面跳转,支持三种跳转场景:

① 跳转到命名路由 (推荐使用) ② 跳转到带参数的命名路由

③ 跳转到外部URL(如 http://example.com

语法:

python 复制代码
redirect(to, *args, permanent=False, **kwargs)

① to:目标URL(可以是命名路由名、路径字符串、外部 URL)

② permanent:是否为永久重定向(True对应301状态码,False对应302,默认为False)

③ args/kwargs:传递给命名路由的参数

举例:

python 复制代码
# myapp/views.py
from django.shortcuts import redirect, render, get_object_or_404
from django.urls import reverse
from .models import Article

def add_article(request):
    """添加文章后重定向到文章详情页"""
    if request.method == 'POST':
        title = request.POST.get('title')
        content = request.POST.get('content')
        # 创建文章
        article = Article.objects.create(title=title, content=content)
        # 场景1:跳转到带参数的命名路由(推荐)
        return redirect('article_detail', pk=article.pk)  # 等价于 reverse('article_detail', args=[article.pk])
    
    # GET请求:显示添加文章表单
    return render(request, 'add_article.html')

def redirect_to_home(request):
    """跳转到首页(命名路由为'home')"""
    # 场景2:跳转到无参数的命名路由
    return redirect('home')

def redirect_to_external(request):
    """跳转到外部URL(如Django官网)"""
    # 场景3:跳转到外部链接
    return redirect('https://www.djangoproject.com/')

1.3 get_object_or_404():查询对象或返回404

查询单个对象时,若对象不存在,自动抛出 Http404异常(返回404页面),无需手动写 try-except捕获DoesNotExist 异常,代码简洁明了

语法:

python 复制代码
get_object_or_404(klass, *args, **kwargs)

① klass:模型类(如Article)或查询集

② *args/**kwargs:查询条件

举例:

python 复制代码
# 优化前:手动try-except
def article_detail_old(request, pk):
    try:
        article = Article.objects.get(pk=pk)
    except Article.DoesNotExist:
        raise Http404('文章不存在')
    return render(request, 'article_detail.html', {'article': article})

# 优化后:用get_object_or_404()
from django.shortcuts import get_object_or_404

def article_detail(request, pk):
    # 若找不到pk=pk的Article,自动返回404
    article = get_object_or_404(Article, pk=pk, is_published=True)  # 可加额外条件(如仅查询已发布文章)
    return render(request, 'article_detail.html', {'article': article})

1.4 get_list_or_404():查询列表或返回404

与 get_object_or_404()类似,但用于查询**多个对象(查询集):**若查询集为空,自动返回 404 页面;若有数据,返回查询集

语法:

python 复制代码
get_list_or_404(klass, *args, **kwargs)

参数与 get_object_or_404()一致,返回值为查询集(而非单个对象)

举例:

python 复制代码
from django.shortcuts import get_list_or_404

def published_articles(request):
    """查询已发布的文章列表,为空则返回404"""
    # 若没有is_published=True的文章,自动返回404
    articles = get_list_or_404(Article, is_published=True)
    return render(request, 'article_list.html', {'articles': articles})

二、视图装饰器:增强视图功能

视图装饰器是 Python 装饰器在 Django 视图中的应用,用于在不修改视图函数代码的前提下,为其添加额外功能(如限制 HTTP 方法、要求登录、缓存页面)。Django 提供了多个内置装饰器,也支持自定义

2.1 限制 HTTP 方法:控制请求类型

最常用的装饰器之一,用于限制视图仅接受特定的 HTTP 方法(如仅 GET、仅 POST),避免非法请求(如用 DELETE 方法访问列表页)

常用装饰器:

① @require_http_methods(['方法1', '方法2']):仅允许指定的 HTTP 方法

② @require_GET:仅允许 GET 方法(等价于@require_http_methods(['GET']));

③ @require_POST:仅允许 POST 方法(等价于@require_http_methods(['POST']));

④ @require_safe:仅允许 GET 和 HEAD 方法(安全方法,不修改数据)

举例:

python 复制代码
# myapp/views.py
from django.views.decorators.http import require_http_methods, require_GET, require_POST
from django.shortcuts import render, redirect
from .models import Article

# 1. 仅允许GET和POST方法
@require_http_methods(['GET', 'POST'])
def edit_article(request, pk):
    article = get_object_or_404(Article, pk=pk)
    if request.method == 'GET':
        # GET:显示编辑表单
        return render(request, 'edit_article.html', {'article': article})
    elif request.method == 'POST':
        # POST:处理表单提交
        article.title = request.POST.get('title')
        article.content = request.POST.get('content')
        article.save()
        return redirect('article_detail', pk=article.pk)

# 2. 仅允许GET方法(显示文章列表)
@require_GET
def article_list(request):
    articles = Article.objects.all()
    return render(request, 'article_list.html', {'articles': articles})

# 3. 仅允许POST方法(处理表单提交)
@require_POST
def delete_article(request, pk):
    article = get_object_or_404(Article, pk=pk)
    article.delete()
    return redirect('article_list')

效果:当使用不允许的方法访问时(如用 PUT 访问edit_article),Django 会自动返回405 Method Not Allowed响应

2.2 @gzip_page:压缩响应内容

用于对视图返回的响应内容进行 Gzip 压缩,减少网络传输数据量,提升页面加载速度(尤其适合大文本响应,如 HTML、JSON)

举例:

python 复制代码
from django.views.decorators.gzip import gzip_page
from django.http import HttpResponse

# 压缩响应内容
@gzip_page
def large_response(request):
    """返回大文本响应,自动压缩"""
    # 模拟大文本(如长文章、大量数据)
    large_text = 'Django 视图装饰器...' * 1000
    return HttpResponse(large_text)

注意:仅在生产环境生效,开发环境(DEBUG=True)下可能不压缩

2.3 其他常用装饰器

(1)@login_required:要求用户登录

限制视图仅允许已登录用户访问,未登录用户会被重定向到登录页面(需在settings.py中配置LOGIN_URL

举例:

python 复制代码
from django.contrib.auth.decorators import login_required
from django.shortcuts import render

# 要求登录才能访问个人资料页
@login_required(login_url='/login/')  # 未登录时重定向到/login/
def user_profile(request):
    # request.user 为当前登录用户(已通过认证)
    return render(request, 'profile.html', {'user': request.user})

配置LOGIN_URL(可选,默认/accounts/login/):

python 复制代码
# settings.py
LOGIN_URL = '/login/'  # 未登录用户的重定向地址

(2)@permission_required:要求用户有特定权限

限制视图仅允许具有指定权限的用户访问(如 "修改文章" 权限),未授权用户返回 403 页面

python 复制代码
from django.contrib.auth.decorators import permission_required
from django.shortcuts import get_object_or_404, render
from .models import Article

# 要求用户有"修改文章"权限(权限名格式:app_label.permission_name)
@permission_required('myapp.change_article', raise_exception=True)
def edit_article(request, pk):
    """仅允许有修改权限的用户编辑文章"""
    article = get_object_or_404(Article, pk=pk)
    # 编辑逻辑...
    return render(request, 'edit_article.html', {'article': article})

'myapp.change_article':权限名,myapp是应用名,change_article是 Django 自动为Article模型生成的权限(默认有add/change/delete/view四种权限);

raise_exception=True:未授权时直接返回 403,而非重定向

(3)@csrf_exempt:豁免 CSRF 保护

Django 默认对 POST 请求进行 CSRF 保护(需在表单中添加{% csrf_token %}),但对于 API 接口(如接收外部服务的 POST 请求),可能需要豁免 CSRF 验证

python 复制代码
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
import json

# 豁免CSRF保护(仅用于API接口,谨慎使用)
@csrf_exempt
def api_receive_data(request):
    if request.method == 'POST':
        # 接收外部POST数据(无需CSRF令牌)
        data = json.loads(request.body)
        # 处理数据...
        return JsonResponse({'status': 'success', 'data': data})
    return JsonResponse({'status': 'error'}, status=400)

警告:仅在确认安全的场景下使用(如内部 API),公开接口需用其他认证方式(如 Token)

(4)@cache_page:缓存页面响应

缓存视图返回的响应,指定时间内重复请求会直接返回缓存结果,无需重新执行视图逻辑(提升高频访问页面的性能)

python 复制代码
from django.views.decorators.cache import cache_page
from django.shortcuts import render

# 缓存15分钟(单位:秒)
@cache_page(60 * 15)
def popular_articles(request):
    """热门文章列表:15分钟内仅执行一次视图逻辑"""
    # 耗时查询(如排序、过滤大量数据)
    articles = Article.objects.all().order_by('-views')[:10]
    return render(request, 'popular_articles.html', {'articles': articles})

注意:缓存基于 URL,不同 URL(如/popular/?page=1/popular/?page=2)会分别缓存

三、内置视图:直接复用的"现成功能"

Django 提供了一些内置视图,封装了常见场景的完整逻辑(如处理静态文件、错误页面),无需自己编写视图函数,直接配置路由即可使用

3.1 serve:开发环境处理媒体文件

在开发环境中,Django 默认不处理用户上传的媒体文件(如头像、附件),需用django.views.static.serve视图手动配置媒体文件的访问路径

配置步骤

python 复制代码
# 项目主 urls.py
from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.views.static import serve
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    # 配置媒体文件访问:/media/xxx/ → 映射到settings.MEDIA_ROOT/xxx
    path('media/<path:path>/', serve, {'document_root': settings.MEDIA_ROOT}),
]

# (可选)开发环境静态文件配置(Django 1.11+ 可省略,自动处理)
if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

配置MEDIA_ROOTMEDIA_URL

python 复制代码
# settings.py
import os

# 媒体文件存储路径(用户上传的文件会保存在这里)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# 媒体文件访问URL前缀(如 /media/avatar.jpg)
MEDIA_URL = '/media/'

注意:仅用于开发环境,生产环境需用 Nginx/Apache 处理媒体文件

3.2 内置错误视图

Django 提供了 4 个内置错误视图,对应 400、403、404、500 错误,可直接复用或自定义模板

|---------------------------|-----------------------------------------|---------|
| 错误类型 | 内置视图 | 作用 |
| 400 Bad Request | django.views.defaults.bad_request | 请求参数错误 |
| 403 Permission Denied | django.views.defaults.permission_denied | 权限不足 |
| 404 Page Not Found | django.views.defaults.page_not_found | 页面不存在 |
| 500 Internal Server Error | django.views.defaults.server_error | 服务器内部错误 |

自定义内置错误视图的模板

无需修改视图,只需在templates目录下创建对应模板文件(如404.html),Django 会自动使用自定义模板:

html 复制代码
<!-- templates/404.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>404 - 页面未找到</title>
</head>
<body>
    <h1>抱歉,你访问的页面不存在!</h1>
    <a href="{% url 'home' %}">返回首页</a>
</body>
</html>

四、请求与响应对象:处理复杂数据交互

Django 封装了HttpRequest(请求)和HttpResponse(响应)对象,用于处理 HTTP 请求的所有信息(如参数、头信息、文件)和返回多样化的响应(如 HTML、JSON、文件)

4.1 HttpRequest对象:获取请求的所有信息

HttpRequest对象由 Django 自动创建,作为视图函数的第一个参数(通常命名为request),包含请求的所有信息

核心属性与方法
属性 / 方法 描述 示例
request.method HTTP 请求方法(大写字符串,如'GET''POST' if request.method == 'POST':
request.GET GET 请求参数(QueryDict对象,类似字典) page = request.GET.get('page', 1)
request.POST POST 请求参数(表单数据,QueryDict对象) title = request.POST.get('title')
request.META 请求头信息(字典,键为大写,前缀HTTP_ user_agent = request.META.get('HTTP_USER_AGENT')
request.COOKIES 请求中的 Cookie(字典) session_id = request.COOKIES.get('sessionid')
request.FILES 上传的文件(MultiValueDict对象) avatar = request.FILES.get('avatar')
request.user 当前登录用户(User对象,未登录为AnonymousUser if request.user.is_authenticated:
request.path 请求的路径(不含域名和查询参数) /article/1/

实战示例:获取请求数据

python 复制代码
def handle_request(request):
    # 1. 获取请求方法
    method = request.method  # 'GET' 或 'POST'

    # 2. 获取GET参数(如 /search/?q=django)
    search_query = request.GET.get('q', '')  # 默认值为空字符串

    # 3. 获取POST参数(表单提交)
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

    # 4. 获取请求头(如用户代理)
    user_agent = request.META.get('HTTP_USER_AGENT')  # 浏览器信息

    # 5. 获取上传文件(如头像)
    avatar = request.FILES.get('avatar')  # 需表单设置 enctype="multipart/form-data"

    # 6. 获取当前用户
    if request.user.is_authenticated:
        user_info = f"当前用户:{request.user.username}"
    else:
        user_info = "未登录"

    return HttpResponse(f"方法:{method}<br>查询:{search_query}<br>{user_info}")

4.2 HttpResponse及其子类:返回多样化响应

HttpResponse是所有响应对象的基类,Django 还提供了多个子类,用于返回特定类型的响应(如 JSON、文件)

(1)基础HttpResponse:返回文本响应

用于返回简单文本、HTML 等响应,可设置响应头和 Cookie

python 复制代码
from django.http import HttpResponse

def simple_response(request):
    # 1. 基础文本响应
    response = HttpResponse('Hello, Django!', status=200)

    # 2. 设置响应头
    response['Content-Type'] = 'text/plain'  # 响应类型
    response['X-Custom-Header'] = 'MyValue'  # 自定义头

    # 3. 设置Cookie(max_age单位:秒)
    response.set_cookie('name', 'Django', max_age=3600)  # 1小时有效期

    # 4. 删除Cookie
    response.delete_cookie('old_name')

    return response

(2)JsonResponse:返回 JSON 响应

专门用于返回 JSON 格式的响应(如 API 接口),自动设置Content-Type: application/json,无需手动序列化字典

python 复制代码
from django.http import JsonResponse

def api_data(request):
    # 字典数据(自动序列化为JSON)
    data = {
        'status': 'success',
        'data': {
            'articles': [
                {'id': 1, 'title': 'Django路由'},
                {'id': 2, 'title': 'Django视图'}
            ]
        }
    }
    # 返回JSON响应(safe=True表示data必须是字典,否则需设为False)
    return JsonResponse(data)

返回列表数据(需设safe=False):

python 复制代码
def api_list(request):
    articles = [{'id': 1, 'title': 'Django'}, {'id': 2, 'title': 'Python'}]
    return JsonResponse(articles, safe=False)  # 列表需设safe=False

(3)StreamingHttpResponse:流式传输大文件

用于返回大型文件(如视频、压缩包),避免一次性加载整个文件到内存,而是分块传输

python 复制代码
from django.http import StreamingHttpResponse
import os

def stream_large_file(request):
    # 大文件路径
    file_path = os.path.join(settings.MEDIA_ROOT, 'large_file.mp4')
    file_size = os.path.getsize(file_path)

    # 定义文件迭代器:分块读取文件
    def file_iterator(file_path, chunk_size=8192):
        with open(file_path, 'rb') as f:
            while True:
                chunk = f.read(chunk_size)  # 每次读取8KB
                if not chunk:
                    break
                yield chunk

    # 流式响应
    response = StreamingHttpResponse(
        file_iterator(file_path),
        content_type='video/mp4'  # 视频文件类型
    )
    # 设置文件大小(可选,用于进度条)
    response['Content-Length'] = str(file_size)
    return response

(4)FileResponse:返回文件下载

StreamingHttpResponse的子类,专门用于返回文件下载,自动处理文件读取和响应头设置

python 复制代码
from django.http import FileResponse
import os

def download_file(request):
    # 文件路径
    file_path = os.path.join(settings.MEDIA_ROOT, 'document.pdf')
    # 打开文件(rb:二进制只读)
    file = open(file_path, 'rb')

    # 文件响应:自动设置Content-Type和下载头
    response = FileResponse(
        file,
        content_type='application/pdf'  # PDF文件类型
    )
    # 设置Content-Disposition:触发浏览器下载(而非预览)
    response['Content-Disposition'] = 'attachment; filename="document.pdf"'
    return response

五、模板响应对象:延迟渲染模板

普通render()会立即渲染模板并返回响应,而 "模板响应对象"(SimpleTemplateResponseTemplateResponse)允许在返回响应前延迟渲染模板,并对模板进行后期处理(如修改上下文、添加响应头)

5.1 SimpleTemplateResponse:基础延迟渲染

python 复制代码
from django.template.response import SimpleTemplateResponse

def delayed_render(request):
    # 1. 创建模板响应对象(未渲染)
    context = {'name': 'Django'}
    response = SimpleTemplateResponse('index.html', context)

    # 2. 延迟处理:返回前修改上下文
    response.context_data['version'] = '5.0'  # 模板中可访问{{ version }}

    # 3. 返回响应(此时才渲染模板)
    return response

5.2 TemplateResponse:支持请求上下文

SimpleTemplateResponse的子类,自动包含请求上下文(如request对象、user对象),无需手动传递

python 复制代码
from django.template.response import TemplateResponse

def template_response(request):
    # 创建TemplateResponse,自动包含请求上下文
    response = TemplateResponse(request, 'index.html', {'name': 'Django'})

    # 添加"渲染后回调":模板渲染完成后执行
    def post_render_callback(response):
        # 在响应内容末尾添加注释
        response.content += b' <!-- 渲染完成 -->'
        return response

    # 注册回调函数
    response.add_post_render_callback(post_render_callback)

    return response

六、文件上传:实现用户上传功能

Django 支持用户上传文件(如头像、附件),需通过 "表单 + 视图" 配合实现,核心是处理request.FILES中的上传文件

6.1 步骤 1:定义文件上传表单

需在表单中设置enctype="multipart/form-data"(否则无法传递文件数据),可使用 Django 的Form类简化表单验证

python 复制代码
# myapp/forms.py
from django import forms

class UploadAvatarForm(forms.Form):
    """用户头像上传表单"""
    # FileField:文件上传字段,自动验证文件类型
    avatar = forms.FileField(
        label="选择头像",
        help_text="支持JPG、PNG格式,不超过5MB"
    )
    # 可选:添加其他字段(如用户名)
    username = forms.CharField(max_length=100, label="用户名")

6.2 步骤 2:编写上传视图

处理 GET 请求(显示表单)和 POST 请求(处理文件上传),将上传的文件保存到指定目录(如media/avatars/

python 复制代码
# myapp/views.py
from django.shortcuts import render, redirect
from .forms import UploadAvatarForm
import os
from django.conf import settings

def upload_avatar(request):
    if request.method == 'POST':
        # 1. 绑定表单数据(request.POST 为普通字段,request.FILES 为文件字段)
        form = UploadAvatarForm(request.POST, request.FILES)
        if form.is_valid():
            # 2. 获取表单数据
            username = form.cleaned_data['username']
            avatar_file = request.FILES['avatar']  # 或 form.cleaned_data['avatar']

            # 3. 保存文件到 media/avatars/ 目录
            # 构造保存路径(避免文件名重复,可加用户名前缀)
            save_dir = os.path.join(settings.MEDIA_ROOT, 'avatars')
            # 确保目录存在(不存在则创建)
            os.makedirs(save_dir, exist_ok=True)
            # 保存文件(分块写入,避免内存溢出)
            with open(os.path.join(save_dir, f"{username}_avatar.jpg"), 'wb+') as destination:
                for chunk in avatar_file.chunks():  # 分块读取上传文件
                    destination.write(chunk)

            # 4. 上传成功,重定向到结果页
            return redirect('upload_success')
    else:
        # GET请求:显示空表单
        form = UploadAvatarForm()

    # 渲染表单页面
    return render(request, 'upload_avatar.html', {'form': form})

def upload_success(request):
    """上传成功页面"""
    return render(request, 'upload_success.html')

6.3 步骤 3:编写上传模板

html 复制代码
<!-- templates/upload_avatar.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>上传头像</title>
</head>
<body>
    <h1>上传用户头像</h1>
    <!-- 必须设置 enctype="multipart/form-data" 才能传递文件 -->
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}  <!-- CSRF保护 -->
        {{ form.as_p }}  <!-- 渲染表单字段(含标签和错误提示) -->
        <button type="submit">上传</button>
    </form>
</body>
</html>

<!-- templates/upload_success.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>上传成功</title>
</head>
<body>
    <h1>头像上传成功!</h1>
    <a href="{% url 'upload_avatar' %}">继续上传</a>
</body>
</html>

6.4 步骤 4:配置媒体文件

确保settings.py中配置了媒体文件路径(参考 3.1 节),并在urls.py中配置媒体文件访问路由

七、总结

本篇覆盖了 Django 视图开发的核心进阶能力,总结如下:

1、快捷函数render()redirect()get_object_or_404()等简化重复逻辑,提升开发效率

2、视图装饰器:控制 HTTP 方法、要求登录 / 权限、缓存页面,增强视图功能

3、请求与响应对象:处理复杂请求数据(如 GET/POST 参数、文件),返回多样化响应(JSON、文件)

4、文件上传:通过表单 + 视图 + 媒体文件配置,实现用户文件上传功能

掌握这些内容后,你已经能应对大多数 Django 视图开发场景 ------ 从简单的页面渲染到复杂的 API 接口、文件处理。结合之前学习的模型与路由知识,你可以搭建起完整的 Django Web 应用骨架,为后续学习模板美化、用户认证等内容打下坚实基础

相关推荐
花菜会噎住4 小时前
Django视图与路由全解析:从URL到页面,一篇讲透
数据库·django·sqlite·函数
爱读源码的大都督5 小时前
为什么有了HTTP,还需要gPRC?
java·后端·架构
码事漫谈5 小时前
致软件新手的第一个项目指南:阶段、文档与破局之道
后端
间彧5 小时前
Spring Boot条件注解详解与项目实战
后端
qq_4924484465 小时前
Jmeter设置负载阶梯式压测场景(详解教程)
开发语言·python·jmeter
im_AMBER5 小时前
Web 开发 27
前端·javascript·笔记·后端·学习·web
间彧5 小时前
ApplicationRunner与CommandLineRunner详解与应用实战
后端
lianyinghhh5 小时前
瓦力机器人-舵机控制(基于树莓派5)
人工智能·python·自然语言处理·硬件工程
Mike_Zhang6 小时前
python3.14版本的free-threading功能体验
python