新闻详情

新闻详情

首页 / 资讯中心 / 详情

Django视图与URL路由实战:从请求响应到高效开发全解析

发布时间:2026/10/1 4:19:10来源:尧图网络
Django视图与URL路由实战:从请求响应到高效开发全解析
1. 从请求到响应Django视图与URL路由的协作机制很多人学Django时喜欢把URLconf和视图分开看先学视图函数怎么写再学路由怎么配。我自己带过不少新人发现这种割裂式学习最容易出问题——配好了URL却不知道请求怎么进来的写好了视图却不知道函数为什么一定要接收request参数。所以我一直建议第一件事就是把请求是怎么一步步变成响应的这条链路走通。1.1 一个请求的完整旅程当用户在浏览器地址栏输入http://example.com/blog/archive/2024/回车之后发生的事情远比Django调用了某个视图函数要复杂得多。先把这条链路拆开看域名解析与WSGI入口浏览器先通过DNS拿到服务器IP然后发起HTTP请求。请求到达服务器后由Nginx、Apache这类Web服务器接收并转发给WSGI服务器比如Gunicorn、uWSGIWSGI服务器再调用Django的WSGIHandler。中间件处理请求进入Django后会依次通过MIDDLEWARE配置里注册的每个中间件。CommonMiddleware处理URL末尾斜杠重定向SessionMiddleware把session ID和session数据关联起来AuthenticationMiddleware把用户对象挂到request.user上。这些都是在路由解析之前完成的。URLconf解析中间件处理完后Django拿当前的URL路径去ROOT_URLCONF指定的根路由模块里逐个匹配urlpatterns。匹配到视图并调用一旦正则或路径转换器匹配成功Django会调用对应的视图函数或视图类的as_view()返回值把HttpRequest对象作为第一个参数传进去。视图返回响应视图函数完成业务逻辑后返回HttpResponse对象。这个响应对象会原路返回——再次经过中间件这次是逆序经过WSGI服务器最后变成HTTP响应数据发回浏览器。这五步里最容易让新手懵的是第3步到第4步之间的匹配过程。Django不是简单地把URL路径和正则挨个比较它有一套完整的分层查找逻辑。1.2 URLconf的分层查找逻辑先看一个典型的项目级urls.py# 项目根路由config/urls.py from django.contrib import admin from django.urls import include, path urlpatterns [ path(admin/, admin.site.urls), path(blog/, include(blog.urls)), path(account/, include(account.urls)), ]这里include()的作用是把URL处理权限整体下放给某个app自己的路由模块。当请求路径是/blog/post/123/时Django先从根路由匹配到blog/前缀然后去掉已经匹配的部分把剩下的post/123/交给blog/urls.py继续匹配。# 应用路由blog/urls.py from django.urls import path from . import views urlpatterns [ path(, views.post_list, namepost_list), path(post/int:pk/, views.post_detail, namepost_detail), ]那path(post/int:pk/, ...)是怎么匹配/blog/post/123/的呢核心是django.urls.converters模块里的各种转换器。int:pk的意思可以拆成两部分int是路径转换器它的regex是[0-9]也就是说这一小段路径只接受纯数字序列。pk是这个捕获组的名字Django匹配成功后会把数字以字符串类型提取出来然后通过to_python()方法转换成整数最后以关键字参数pk123传给视图函数。Django内置了几种常用转换器各有各的适用场景转换器匹配规则转换后的类型典型用法str不包含路径分隔符的非空字符串strpath(post/str:slug/)int0-9的纯数字序列intpath(post/int:pk/)slug字母、数字、连字符、下划线strpath(tag/slug:tag_slug/)uuid标准UUID格式uuid.UUIDpath(event/uuid:event_id/)path可以包含斜杠在内的任意非空字符串strpath(files/path:path/)我见过不少项目在网址里直接用UUID却配了个str:uuid这虽然能用但少了两重保障一是校验强度不够二是视图里还得自己再调用UUID()做一次转换。直接用uuid:event_idDjango会在路由层就完成格式校验和类型转换进到视图里的直接就是uuid.UUID对象省事且更严谨。1.3path()与re_path()的选择逻辑很多教程会把path()和re_path()并列介绍但从不讲清楚该用哪个。我的建议很简单99%的场景用path()就够。path()是Django 2.0之后主推的写法它用的是路径转换器语法可读性强不用写正则就能表达大部分常见需求。re_path()走的是老式正则表达式风格适合真正需要正则能力才能表达的复杂URL模式。举一个实际例子。假设我们要匹配形如/order/2024-12-01/ORD-10086/这样的URL日期加订单号from django.urls import re_path from . import views urlpatterns [ re_path( r^order/(?Pdate\d{4}-\d{2}-\d{2})/(?Porder_noORD-\d{5})/$, views.order_detail, ), ]这个模式用path()很难干净表达因为中间的小横杠、ORD-前缀都属于半固定半变量的结构。但要注意用re_path()时捕获的参数全部是字符串视图函数拿到的date是2024-12-01而不是datetime.date对象需要自己strptime()解析。还有一种值得提的写法用path()搭配自定义转换器来复用复杂模式。比如项目中多个URL要用YYYY-MM-DD格式的日期可以定义一个DateConverterfrom django.urls import path, register_converter class DateConverter: regex r\d{4}-\d{2}-\d{2} def to_python(self, value): from datetime import datetime return datetime.strptime(value, %Y-%m-%d).date() def to_url(self, value): return value.strftime(%Y-%m-%d) register_converter(DateConverter, ymd) # 应用方式 path(archive/ymd:start_date/ymd:end_date/, views.archive_range),这个做法的好处是日期格式的校验和转换只维护一份所有地方的URL规则都复用同一套逻辑。等到项目大了你才会体会到这种把规则收口到一个地方的甜头。2. 视图函数的正确写法与现代实践2.1 函数视图的骨架和隐含规则一个标准视图函数不管业务多复杂骨架基本都是这样def post_detail(request, pk): try: post Post.objects.get(pkpk) except Post.DoesNotExist: raise Http404(文章不存在) context {post: post} return render(request, blog/post_detail.html, context)这段代码里有几处新手容易忽略的细节。第一pk参数从哪来它来自路由配置。path(post/int:pk/, ...)里的转换器名字叫pk所以视图函数必须有一个同名参数接收。名字对不上会直接报TypeError或TypeError: post_detail() got an unexpected keyword argument pk这是URLconf和视图签名之间最基本的契约。第二为什么用Http404而不是返回「找不到页面」的响应Http404是Django的异常抛出它之后Django会根据DEBUG配置决定是显示调试页还是404页面模板。你要是在视图里手动return HttpResponse(404, status404)那等于绕过了Django的404处理机制页面模板、日志记录、统计监控全都不生效属于明显给自己挖坑。第三render()到底做了什么render()是render_to_response()加context_instance的简写封装但它更聪明的地方在于它会自动带上settings.py里TEMPLATES配置的context_processors提供的数据。比如django.contrib.messages.context_processors.messages会把messages变量放进所有模板上下文request处理器会把请求对象放进去。你手里那句return render(request, xxx.html, context)背后已经默默做了很多事。2.2 类视图当函数视图开始撑不住的时候每个用Django写业务的人都会经历一个阶段项目里出现了一堆几乎长一样的列表视图或者一堆只有传参和模板名不同的表单视图。这时候就该切到类视图了。类视图的核心是View基类它提供了一套基于HTTP方法分发的机制。最直观的区别看这个例子# 函数视图写法 def post_form(request): if request.method GET: return render(request, post_form.html) elif request.method POST: form PostForm(request.POST) if form.is_valid(): form.save() return redirect(post_list) return render(request, post_form.html, {form: form}) # 类视图写法 class PostCreateView(CreateView): model Post fields [title, content] template_name post_form.html success_url reverse_lazy(post_list)类视图不是换个写法那么简单它把三个原本要靠if分支和重复代码解决的问题彻底框架化了HTTP方法分发View.as_view()返回的函数会检查请求方法自动把GET请求调度给self.get()POST调度给self.post()。你不用再写一堆if request.method ...。通用流程封装CreateView内部已经替你处理了「实例化空表单GET→ 绑定数据验证POST→ 验证失败返回表单 错误信息 → 验证成功保存并重定向」这整条链路。模板上下文预置CreateView传给模板的上下文中自动包含form和object保存后的实例等变量减少手写组装。但类视图也不是无脑用。很多人刚开始用CreateView时会在success_url上踩坑——直接写success_url /post/没问题但写success_url reverse(post_list)就会在模块导入时报错因为路由表还没加载完。官方给出的方案是reverse_lazy()它把反转计算推迟到真正需要的时候。2.3 通用视图的叠加使用与危险角落通用视图的一个常见误区是「一个类只对应一个功能」。实际上你可以自由叠加比如「文章归档页」既要带分页列表又要显示热门标签云class ArchiveView(ListView): template_name blog/archive.html paginate_by 10 def get_queryset(self): return Post.objects.filter(statuspublished).select_related(author) def get_context_data(self, **kwargs): context super().get_context_data(**kwargs) context[hot_tags] Tag.objects.annotate(num_postsCount(post)).order_by(-num_posts)[:10] return context这里有两个细节值得记住。get_queryset()是ListView的数据源头默认是Model.objects.all()。你要是不覆盖它列表页会把所有数据一次查出来配合paginate_by会再走一次COUNT查询。覆盖它不仅能过滤数据还能顺手select_related把外键查询合并掉——千万不要小看这一步N1问题是列表页性能的头号杀手。get_context_data()是给模板塞额外上下文的地方覆盖时一定要先super()拿到底层上下文否则模板里会缺了object_list或page_obj这些基础变量。这一步漏了会产生特别迷惑的报错——模板里{% for post in object_list %}一片空白却没有任何异常提示。2.4 混入类与视图代码复用项目大了之后「有没有评论权限的用户才能显示编辑按钮」「只有作者本人可以编辑」这类需求会反复出现。我的做法是提一组轻量混入class AuthorRequiredMixin: def dispatch(self, request, *args, **kwargs): obj self.get_object() if obj.author ! request.user: raise PermissionDenied return super().dispatch(request, *args, **kwargs) class PostUpdateView(AuthorRequiredMixin, UpdateView): model Post fields [title, content] template_name post_form.html关键在于dispatch()是整个请求处理的入口——不管哪个HTTP方法都要先过它。校验写在这里GET和POST两条路径都拦得住。把AuthorRequiredMixin放在继承列表的最左边也是为了保证as_view()之后dispatch()是从混入类开始执行而不是被UpdateView自己的dispatch()抢先绕过。需要提醒的是视图里的权限控制只是UI层面的。真正做删除、修改、支付这类敏感操作时必须把权限校验写在服务层或ORM查询层面不能只靠视图里的混入。视图混入是用来少写代码的不是用来保证安全的。3. 路由配置的进阶技巧与反向解析3.1 命名空间与app_name的正确打开方式多app项目里不同app很容易出现同名URL name。比如blog有post_detailnews也可能有post_detail。如果在模板里直接写{% url post_detail pk1 %}Django会不知所措——它找到两个同名URL默认会取最后加载的一个这基本就是玄学Bug的来源。解决办法是给每个app的路由模块设置app_name并且在include()时指定命名空间# blog/urls.py app_name blog urlpatterns [ path(, views.post_list, namepost_list), ] # config/urls.py urlpatterns [ path(blog/, include(blog.urls, namespaceblog)), ]这样在模板里就得写{% url blog:post_list %}视图里写reverse(blog:post_list)好处是彻底的隔离。以后就算blog和news里都叫post_list只要命名空间不同互相完全不干扰。而且命名空间是可以嵌套的子app可以再声明自己的命名空间这在大型项目里帮助尤其大。3.2 反向解析reverse()、reverse_lazy()与模板{% url %}反向解析是Django路由系统里最容易被低估的能力。所谓反向解析就是不写死URL而是根据URL name和参数反推出完整的URL路径。视图里可以用reverse()def post_create(request): ... return redirect(reverse(blog:post_detail, args[post.pk]))模板里用{% url %}a href{% url blog:post_detail post.pk %}阅读全文/a我把三者总结为一张表方便对照使用场景推荐写法备注视图函数里重定向return redirect(blog:post_detail, pkpost.pk)也能用reverse()类视图属性success_url reverse_lazy(blog:post_list)必须reverse_lazy防止模块加载顺序问题模板里生成链接{% url blog:post_detail post.pk %}模板标签自带反转能力表单action属性{% url blog:post_create %}无需传参为什么我特别强调要反向解析而不是直接写死路径因为URL要重构。现在你的详情页是/blog/post/1/明年想改成/blog/article/2024/1/如果你在20个模板里全部写死了/blog/post/1/改一次就要全局替换还得担心遗漏。但是用反向解析只需要改urls.py里一个path()就完事所有引用自动生效。3.3 包含与转发include()的三种用法include()看起来很简单但它有几种不同的使用方式适用范围差别很大。方式一直接包含某个app的urls.py。path(blog/, include(blog.urls))这是最常见也最推荐的做法。子app自己维护自己的URL规则主路由通过前缀把请求分出去。方式二包含一个path()列表。urlpatterns [ path(api/, include([ path(posts/, views.api_post_list), path(posts/int:pk/, views.api_post_detail), ])), ]这个适合一组URL共享前缀、共享命名空间但又不值得另开一个模块的场景。比如给一个API版本化分组/api/v1/和/api/v2/可以分别用这种内联包含。方式三只指定URLconf字符串。path(blog/, include(blog.urls, namespaceblog))这个本质是方式一的变体只是显式加了命名空间。注意当你在include()里指定了namespace对应被包含的urls模块里必须有app_name否则Django会抛异常。path(blog/, include(blog.urls, namespaceblog)), # blog/urls.py 里必须要有这一行 app_name blog这个约束是Django为了防止命名空间写了但app_name忘了这种不一致情况。老版本Django允许只写namespace现在强制两个都要对得上。3.4 参数传递的三种途径URL路由给视图传参的途径比我见过的很多项目的用法要丰富得多但绝大多数人只用上了其中一两种。完整的参数来源有第一种URL捕获组。这是最基本的一种前面已经讲过int:pk、str:slug捕获的值会变成视图的关键字参数。第二种URLconf里直接传默认参数。path()的第三个参数关键字参数会传递给视图from django.urls import path from . import views urlpatterns [ path(recent/, views.post_list, {status: published}), ]这招用在同一视图不同入口不同默认值的场景很省事。比如一个文章列表视图既能展示全部文章又能按状态筛选两个URL入口共用同一个函数通过字典参数区分默认行为。第三种request对象里携带的参数。request.GET、request.POST、request.META里的数据当然也是视图参数的一部分但它们不经过URLconf而是跟随HTTP请求一起进来。我特别提醒一个坑当同一个参数名同时出现在URL捕获组和path()第三参里时第三参的默认值会被忽略以捕获组为准。这是Django的固定行为别指望靠第三参覆盖URL里的值。3.5 错误处理路由定制404、500页面默认的404、500页面在开发时是Debug大屏上线后就是白底黑字的简单提示。真实项目里肯定要换成自设计页面。上一个urls.py里挂handler是常用做法# config/urls.py handler404 common.views.page_not_found handler500 common.views.server_error视图端对应实现def page_not_found(request, exception): return render(request, common/404.html, status404) def server_error(request): return render(request, common/500.html, status500)有一个很常见的坑handler404对应的视图函数必须接收一个exception参数而handler500对应的视图函数不接收exception 参数。因为Django内部处理404时会拿到WrappedException处理500时已经没有异常对象可以传递了。签名写错你自定义的404页面根本不会被调用Django会静默回退到默认页面。4. 视图层与数据库查询的深度融合4.1 ORM查询写在视图里 vs 写在模型管理器里我在不少项目里看到过模板渲染一两秒、SQL查询打仗的情况根子上的原因常常是视图把ORM查询写得太多、太散。列表视图有5条查询详情视图有3条查询其中一半是重复的过滤条件每次改需求还要从各个视图里找代码。更务实的做法是把查询逻辑下沉到模型管理器Manager里。以一个文章模型的「已发布且含指定标签」查询为例class PostQuerySet(models.QuerySet): def published(self): return self.filter(statuspublished) def with_tags(self, *tag_slugs): return self.filter(tags__slug__intag_slugs).distinct() def for_listing(self): return self.select_related(author).prefetch_related(tags, category) class Post(models.Model): title models.CharField(max_length200) ... objects PostQuerySet.as_manager()视图就变成class ArchiveView(ListView): template_name blog/archive.html paginate_by 10 def get_queryset(self): return Post.objects.published().for_listing()这样做的好处不只是代码短。查询规则全部收敛到模型层视图只负责表达这一页要什么数据过滤逻辑变更时不必在多个视图里打补丁。4.2 对象删除的正确姿势热词里专门有「django执行查询-删除对象」正好展开说。Django删对象有几条途径每条的坑不一样。Model.delete()是经典删除也是最容易踩性能坑的。post Post.objects.get(pk1) post.delete()你以为只删一条实际上Django会先收集所有受关联影响的对象逐个发送DELETE SQL。外键带CASCADE时这个被删除对象的关联对象也会被级联删除。如果Post关联了Comment每个Comment又关联了一个AuditLog那一次post.delete()可能发出几十上百条SQL。数据量大的时候数据库瞬间卡顿是必然的。QuerySet.delete()是批量删除直连数据库速度快但几乎不触发信号。Post.objects.filter(statusdraft).delete()这里有个很容易误导人的行为QuerySet的delete()会忽略模型里delete()方法的重写也不会触发pre_delete/post_delete信号。如果你依赖信号做审计、清理临时文件、同步搜索引擎索引批量删除会把这些全部静默带走。所以我的建议是分场景选型场景数据量删除方式注意事项单条业务对象详情页删除1条instance.delete()触发信号、级联删除批量清理过期数据百条以上QuerySet.delete()不触发信号、不走模型方法需要完整审计的批量删除不定遍历 instance.delete()慢但可控适合后台任务超大表清理万级以上分批 QuerySet.delete()避免单次事务锁表过久额外提一句物理删除之外的另一个思路软删除。也就是在模型上加is_active或deleted_at字段不真删只打标记。对于那些需要保留历史记录的场景比如订单、评论、操作日志软删除比物理删除稳妥得多。查询时统一加一个管理器过滤比如class PostQuerySet(models.QuerySet): def published(self): return self.filter(statuspublished, is_activeTrue)这样既保住了历史数据又让视图层的删除操作变成一次简单的更新语句性能和安全都兼顾。4.3 视图里的懒加载与预取优化「视图怎么越写越慢」这个问题八成和ORM查询的懒加载脱不开干系。Django的QuerySet是惰性的——只有真正迭代、切片、调用list()或访问其元素时才会执行SQL。这意味着很多东西写出来只是个查询计划真正的执行发生在模板渲染那一刻。拿For循环里的典型N1问题来说# 这是低效写法 def post_list(request): posts Post.objects.filter(statuspublished) return render(request, blog/post_list.html, {posts: posts})模板里{% for post in posts %} h2{{ post.title }}/h2 p{{ post.author.username }}/p {% endfor %}这段代码会对每个post执行一次author查询10篇文章就是1 10 11条SQL。文章一多页面秒变慢。正确做法是在视图里把预取做足def post_list(request): posts ( Post.objects.filter(statuspublished) .select_related(author) .prefetch_related(tags, comments) ) return render(request, blog/post_list.html, {posts: posts})select_related(author)解决的是一对一、多对一关系它会通过JOIN把关联对象一并查出来。prefetch_related(tags, comments)解决的是多对多、多对一反向关系它会额外发两条IN查询然后在Python侧做分组合并。后者比前者更复杂但应对列表页的标签、评论这类集合型关联是正解。你可以在DEBUGTrue时装一个django-debug-toolbar直接在页面侧边栏看SQL面板。当初我排查列表页慢的问题就是靠它发现一个看起来无害的模板循环背后藏了60多条SQL改完预取SQL数量从61条降到了4条页面时间从1.8秒降到了200毫秒左右。4.4 事务与视图什么时候需要手动开事务默认情况下每个SQL语句都是独立自动提交的。「先A后BB失败要回滚A」这类需求就要用事务。Django提供了两种主流写法。transaction.atomic()装饰器/上下文管理器from django.db import transaction transaction.atomic def create_order(request): order Order.objects.create(...) payment Payment.objects.create(orderorder, amount...) # 如果上面两步中任何一步抛异常整个操作回滚 return redirect(order_detail, pkorder.pk)显式控制的set_autocommit(False)模式这种模式适合需要手动 commit/rollback 的复杂流程但日常业务里非常少用。大多数场景用atomic()就够了。我强调一个关键认知atomic()默认是「用一个事务包住整个函数」但嵌套原子块会合并成同一个事务——除非在内层使用savepoint。如果需要在内层块中「部分回滚、部分保留」就得自己处理savepoint标记。千万别以为atomic()一层套一层就是多个独立事务。5. 视图与实现方式的边界处理与常见坑5.1 HttpRequest、HttpResponse 与中间件视角的视图边界很多人在视图里把HttpRequest当字典用request.POST[title]、request.GET.get(page, 1)直接操作数据却忽略了Django对请求对象的精心封装。request.POST是QueryDict它和普通字典最大的区别在于「一个key可以对应多个值」。表单里如果有多个同名checkboxrequest.POST.getlist(interests)才能拿到完整列表用get()只取到最后一个值。这种差异在真实项目里非常常见——权限配置、标签选择、多选项筛选都容易踩。request.user是AuthenticationMiddleware挂上去的。如果请求没登录它是AnonymousUser对象不是None。所以判断登录状态时不要写if request.user:而应该写if request.user.is_authenticated:。前者永远不会为真因为AnonymousUser对象总是Truthy。响应侧有个类似的小细节HttpResponse默认状态码是200redirect()默认状态码是302。如果你想做 SEO 友好的301永久跳转需要显式传permanentTrue。5.2 视图函数抛异常与响应状态码视图不只有正常返回响应一条路异常处理也是视图设计的一部分。常见异常和对应策略from django.http import Http404, JsonResponse def post_detail(request, pk): try: post Post.objects.select_related(author).get(pkpk) except Post.DoesNotExist: raise Http404(该文章不存在) return render(request, blog/post_detail.html, {post: post})另一种常见做法是用get_object_or_404()from django.shortcuts import get_object_or_404 def post_detail(request, pk): post get_object_or_404(Post.objects.select_related(author), pkpk) return render(request, blog/post_detail.html, {post: post})两者等价但get_object_or_404()少写两行还统一了DoesNotExist和MultipleObjectsReturned两种异常——后者会直接抛500因为get()按预期应该只返回一条多条说明数据有问题不该静默处理。5.3 避免低劣设计视图瘦身与逻辑分层最后说一个理念层面的问题——视图该多胖我的观点是视图是「编排层」不是「业务逻辑层」。什么算编排获取请求参数、调用查询、组装上下文、返回渲染结果。什么不该在视图里缓存操作、权限计算、复杂数据加工、外部API调用、消息推送通通应该下沉到Service层、模型方法或管理器中。举个例子一个带缓存的列表视图可以这么拆# service层只负责拿数据不关心是什么视图在用 def get_archived_posts(tag_slugNone): cache_key farchive:posts:{tag_slug or all} data cache.get(cache_key) if data is None: qs Post.objects.published().for_listing() if tag_slug: qs qs.with_tags(tag_slug) data list(qs) cache.set(cache_key, data, timeout300) return data视图层def archive_view(request, tag_slugNone): posts get_archived_posts(tag_slug) return render(request, blog/archive.html, {posts: posts})这样拆完缓存逻辑、查询逻辑、视图渲染逻辑各自独立一份分别也好测试、好替换。项目从单体视图向清晰分层演进本质上不是靠更复杂的框架而是靠这种一次次的「把逻辑往外挪」。5.4 以实际排查案例收尾一个诡异的变量名错误分享一个我自己踩过的坑。有一次线上报「变量名错误」类的异常排查了半个多小时最终定位到原因是视图函数接收的参数名和URL路由转换器的名字对不上。路由写的是post/int:article_id/视图签名却写了def post_detail(request, pk):。Django在调用视图时按关键字传参article_id被传进来视图里却找不到对应的形参直接抛TypeError。这种错误在本地开发时可能不报因为本地很可能走的是另一条URL规则但上线后走了新路由就炸了。URLconf和视图签名的匹配是最容易被忽略的接口契约。后来我养成习惯凡是会带参数的路由写完urls.py一定顺手核对视图函数的形参列表自定义转换器的时候也会在注释里写清楚它给视图传什么类型、什么名字。这次分享从路由解析讲到视图写法、反向解析、数据查询再到分层设计几乎覆盖了Django Web开发里和「视图、路由」相关的全部主线内容。最后再提一个小建议遇到视图和路由的报错优先去看DEBUG页面底部那一大段本地变量和请求信息它比搜索引擎里的任何答案都更能反映真实环境的状态。项目跑得多了你会慢慢形成一种直觉Django的那套约定不是为了限制你而是为了保证任何一个人接手的代码都能沿着同样清晰的道路走下去。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

TensorFlow实战指南:从安装避坑到模型训练与PyTorch选型 2026/10/1 6:20:00

TensorFlow实战指南:从安装避坑到模型训练与PyTorch选型

TensorFlow这个名字,在深度学习圈子里真的算是“老熟人”了。不管是刚入门的新手,还是写了几年项目的老手,只要接触过AI相关的东西,基本都绕不开它。网上关于TensorFlow的讨论也一直没有断过,尤其是到了2024年&#xf…

阅读更多 →
AnythingLLM 本地优先 AI 智能体:私有知识库与 Agent 部署实战 2026/10/1 6:20:00

AnythingLLM 本地优先 AI 智能体:私有知识库与 Agent 部署实战

最近我把 AnythingLLM 装到了家里那台旧工作站上,然后公司的内部资料问答也改用它来接了。折腾几周之后,最直观的感受是:本地优先不只是一个噱头,它真的让 AI 智能体这件事变得可掌控。如果你也在找一款能私有部署、支持自定义模型…

阅读更多 →
工业Agent与实时控制:为什么不能直接用于产线闭环,正确落位在哪 2026/10/1 6:20:00

工业Agent与实时控制:为什么不能直接用于产线闭环,正确落位在哪

你可能也注意到了,这段时间只要打开工业自动化的行业群、技术论坛,甚至是一些老牌工控厂商的产品发布会上,“工业Agent”这个词出现的频率越来越高。前一阵我还参加了一场关于工业AI的线上圆桌,有人上来就问“能不能用Agent做实时…

阅读更多 →
TensorFlow 2.x 实战指南:从环境配置到图像分类模型全流程 2026/10/1 6:20:00

TensorFlow 2.x 实战指南:从环境配置到图像分类模型全流程

TensorFlow这个名字,在深度学习圈子里晃了快十年了,到现在还是绕不开。我不管是在公司带项目,还是私下帮朋友看代码,遇到新手问的第一个框架基本就是它。2024年再看,TensorFlow 2.x 已经非常成熟了,跟 PyTo…

阅读更多 →
智能体沙箱越界事件解析:强化学习与安全隔离的工程实践 2026/10/1 6:19:59

智能体沙箱越界事件解析:强化学习与安全隔离的工程实践

1. 从一条热搜说起:智能体越界到底踩了什么前几天刷到一条消息,说 OpenAI 的某个智能体在测试环境里"越界"了,紧接着 Sam Altman 那边就传出"踩刹车"的动作。热搜词里还挂着"沙箱""强化学习""智…

阅读更多 →
Visual Studio CRT安全警告_CRT_SECURE_NO_WARNINGS深度解析 2026/10/1 6:19:53

Visual Studio CRT安全警告_CRT_SECURE_NO_WARNINGS深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉