Django REST Framework 渲染 HTML 页面与表单:TemplateHTMLRenderer、StaticHTMLRenderer 与 render_form 模板标签实战指南
发布时间:2026/9/19 6:50:26来源:尧图网络
Django REST Framework 渲染 HTML 页面与表单TemplateHTMLRenderer、StaticHTMLRenderer 与 render_form 模板标签实战指南【免费下载链接】django-rest-frameworkWeb APIs for Django. 项目地址: https://gitcode.com/gh_mirrors/dj/django-rest-frameworkREST framework 不仅能返回 JSON 等 API 风格的响应同样适合渲染常规 HTML 页面更进一步序列化器Serializer可以直接当作 HTML 表单在模板中渲染实现一套校验逻辑、两种输出形态。本文以 docs/topics/html-and-forms.md 为主线结合仓库源码renderers.py、templatetags/rest_framework.py与测试用例tests/test_htmlrenderer.py、tests/test_renderers.py完整讲解 HTML 渲染器、表单渲染、模板包与字段样式定制读完即可在你的 Django 项目里落地可复用的 HTML 视图与序列化器表单。概述API 之外的另一半能力TemplateHTMLRenderer、StaticHTMLRenderer与render_form模板标签构成了 REST framework 的 HTML 输出能力HTML 页面用TemplateHTMLRenderer将 context 字典渲染进指定模板或用StaticHTMLRenderer直接返回预渲染的 HTML 字符串HTML 表单用render_form模板标签把序列化器实例渲染成完整的表单配合style参数定制字段的控件类型与布局。这两类能力与 JSON 渲染等纯 API输出是并行的同一个序列化器的字段声明、校验规则可以复用于 API 响应和 HTML 表单两种场景。渲染 HTML 页面两种 HTML 渲染器返回 HTML 响应需要用到两种渲染器之一渲染器Response 数据类型模板来源TemplateHTMLRenderer字典形式的 context 数据在视图上或 Response 上显式指定模板名StaticHTMLRenderer预渲染完成的 HTML 字符串无需模板直接返回字符串TemplateHTMLRenderer的源码实现印证了这一点其类注释明确说明data 应该是作为模板 context 使用的字典rest_framework/renderers.py而StaticHTMLRenderer直接继承TemplateHTMLRenderer以复用异常渲染逻辑其render方法在非异常场景下原样返回 datarest_framework/renderers.py。模板名的解析优先级源码细节TemplateHTMLRenderer按以下顺序确定模板名见 rest_framework/renderers.py 的get_template_namesResponse 上显式设置的.template_name属性如Response(data, template_nameusers.html)渲染器类上显式设置的.template_name属性如renderer_classes [TemplateHTMLRenderer]配合template_name profile_list.html调用view.get_template_names()的返回值视图上的template_name属性。如果以上都没有配置会抛出ImproperlyConfigured提示在视图或 response 上都没有设置template_name。此外当响应携带异常时渲染器会改用exception_template_names默认为%(status_code)s.html与api_exception.html来渲染错误页rest_framework/renderers.py。为什么通常要显式编写 HTML 视图由于静态 HTML 页面的行为与 API 响应有本质差异——例如表单提交、页面跳转、错误回显等——通常需要显式编写 HTML 视图而不是依赖内置的通用视图Generic Views。这也是下面示例都基于APIView自定义的原因。示例渲染一个 Profile 列表页views.pyfrom my_project.example.models import Profile from rest_framework.renderers import TemplateHTMLRenderer from rest_framework.response import Response from rest_framework.views import APIView class ProfileList(APIView): renderer_classes [TemplateHTMLRenderer] template_name profile_list.html def get(self, request): queryset Profile.objects.all() return Response({profiles: queryset})profile_list.htmlhtmlbody h1Profiles/h1 ul {% for profile in profiles %} li{{ profile.name }}/li {% endfor %} /ul /body/html注意这里Response传入的是字典{profiles: queryset}该字典会整体作为模板 context 使用。仓库中的 tests/test_htmlrenderer.py 提供了一个等价的最小示例用renderer_classes((TemplateHTMLRenderer,))装饰api_view并通过Response(data, template_nameexample.html)在 Response 层面指定模板名验证了模板解析的第一优先级路径。用序列化器渲染 HTML 表单render_form模板标签render_form是 rest_framework/templatetags/rest_framework.py 中注册的 simple tagregister.simple_tag def render_form(serializer, template_packNone): style {template_pack: template_pack} if template_pack else {} renderer HTMLFormRenderer() return renderer.render(serializer.data, None, {style: style})其底层由HTMLFormRendererrest_framework/renderers.py完成渲染当序列化器实例化时没有绑定对象返回的是未绑定的空表单绑定了对象后会以对象数据作为初始值填充表单。需要注意的是当前实现不支持渲染字段级和表单级错误信息源码类注释中明确说明。示例查看并更新一个 Profile 实例views.pyfrom django.shortcuts import get_object_or_404 from my_project.example.models import Profile from rest_framework.renderers import TemplateHTMLRenderer from rest_framework.views import APIView class ProfileDetail(APIView): renderer_classes [TemplateHTMLRenderer] template_name profile_detail.html def get(self, request, pk): profile get_object_or_404(Profile, pkpk) serializer ProfileSerializer(profile) return Response({serializer: serializer, profile: profile}) def post(self, request, pk): profile get_object_or_404(Profile, pkpk) serializer ProfileSerializer(profile, datarequest.data) if not serializer.is_valid(): return Response({serializer: serializer, profile: profile}) serializer.save() return redirect(profile-list)profile_detail.html{% load rest_framework %} htmlbody h1Profile - {{ profile.name }}/h1 form action{% url profile-detail pkprofile.pk %} methodPOST {% csrf_token %} {% render_form serializer %} input typesubmit valueSave /form /body/html关键点模板中必须先{% load rest_framework %}才能使用render_form表单必须带{% csrf_token %}以满足 Django 的 CSRF 校验post方法复用同一份ProfileSerializer完成校验与保存校验失败时把携带错误的 serializer 重新渲染回表单实现错误回显渲染的是带初始值的表单校验成功后redirect到列表页完成经典 PRGPost/Redirect/Get流程。HTMLFormRenderer 的默认样式映射HTMLFormRenderer内置了一张字段类型 → 默认控件模板的映射表default_style见 rest_framework/renderers.py核心条目如下字段类型默认 base_template默认 input_typeField基类input.htmltextEmailFieldinput.htmlemailURLFieldinput.htmlurlIntegerField/FloatFieldinput.htmlnumberDateTimeFieldinput.htmldatetime-localDateField/TimeFieldinput.htmldate/timeFileFieldinput.htmlfileBooleanFieldcheckbox.html—ChoiceField/RelatedFieldselect.html也可用radio.html—MultipleChoiceField/ManyRelatedFieldselect_multiple.html也可用checkbox_multiple.html—Serializer嵌套fieldset.html—ListSerializer/ListField/DictFieldlist_fieldset.html/list_field.html/dict_field.html—JSONFieldtextarea.html—实际渲染时render_fieldrest_framework/renderers.py样式取自默认样式 字段自身的style参数的合并结果若字段通过style{template: ...}指定了完整模板名则优先使用否则按template_pack / base_template拼接模板路径例如rest_framework/vertical/input.html。使用模板包Template Packstemplate_pack参数render_form标签接受可选的template_pack参数用于指定渲染表单及字段控件时使用哪个模板目录。REST framework 内置了三个基于Bootstrap 3的模板包默认样式为horizontal。使用这些模板包时通常还需要引入 Bootstrap 3 的 CSS例如在head中链接 CDN 版本head … link relstylesheet hrefhttps://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css /head第三方包也可以打包自己的模板目录包含必要的 form 与 field 模板来提供备选模板包。为了演示三种模板包的用法下面统一使用一个Login序列化器class LoginSerializer(serializers.Serializer): email serializers.EmailField( max_length100, style{placeholder: Email, autofocus: True} ) password serializers.CharField( max_length100, style{input_type: password, placeholder: Password} ) remember_me serializers.BooleanField()rest_framework/vertical标签位于控件输入框上方采用标准 Bootstrap 布局。这是默认的模板包。{% load rest_framework %} ... form action{% url login %} methodpost novalidate {% csrf_token %} {% render_form serializer template_packrest_framework/vertical %} button typesubmit classbtn btn-defaultSign in/button /formrest_framework/horizontal标签与控件并排采用 2/10 的列宽划分。这是 Browsable API 与 Admin 渲染器使用的表单样式。{% load rest_framework %} ... form classform-horizontal action{% url login %} methodpost novalidate {% csrf_token %} {% render_form serializer %} div classform-group div classcol-sm-offset-2 col-sm-10 button typesubmit classbtn btn-defaultSign in/button /div /div /form注意这里省略了template_pack参数——因为horizontal就是默认值。可以对照 BrowsableAPIRenderer 的form_renderer_class HTMLFormRenderer及其对模板渲染器的选择逻辑理解为何 Browsable API 呈现的是 horizontal 风格的表单。rest_framework/inline紧凑型表单样式所有控件横向内联排列。{% load rest_framework %} ... form classform-inline action{% url login %} methodpost novalidate {% csrf_token %} {% render_form serializer template_packrest_framework/inline %} button typesubmit classbtn btn-defaultSign in/button /form三个内置模板包对应的模板目录位于 rest_framework/templates/rest_framework/ 下的vertical/、horizontal/、inline/三个子目录每个目录都包含form.html、input.html、textarea.html、select.html、checkbox.html等一套完整的表单与字段模板。字段样式定制Field Stylesstyle关键字参数序列化器字段通过style关键字参数定制渲染样式。style是一个选项字典控制使用的模板与布局。最常用的定制方式是base_template键在模板包中选择渲染该字段时使用的模板。例如把CharField从默认的 HTML input 改成多行 textareadetails serializers.CharField( max_length1000, style{base_template: textarea.html} )template使用模板包之外的完全自定义模板如果希望使用不属于任何内置模板包的自定义模板可以用template选项完整指定模板名details serializers.CharField( max_length1000, style{template: my-field-templates/custom-input.html} )这与源码中render_field的逻辑一一对应style[template]存在时直接加载该模板否则才拼接template_pack/base_templaterest_framework/renderers.py。其他 style 属性字段模板还可以使用其他 style 属性具体取决于模板类型。例如textarea.html模板额外支持rows属性控制控件高度details serializers.CharField( max_length1000, style{base_template: textarea.html, rows: 10} )placeholder、autofocus、input_type等也属于常见 style 属性均通过field.style与默认样式合并后传入模板 context。base_template选项完整参考表下表列出全部base_template选项、适用字段类型及附加 style 选项base_template适用的字段类型附加 style 选项input.html任意字符串、数值或日期/时间字段input_type,placeholder,hide_label,autofocustextarea.htmlCharFieldrows,placeholder,hide_labelselect.htmlChoiceField或关系字段类型hide_labelradio.htmlChoiceField或关系字段类型inline,hide_labelselect_multiple.htmlMultipleChoiceField或manyTrue的关系字段hide_labelcheckbox_multiple.htmlMultipleChoiceField或manyTrue的关系字段inline,hide_labelcheckbox.htmlBooleanFieldhide_labelfieldset.html嵌套序列化器hide_labellist_fieldset.htmlListField或manyTrue的嵌套序列化器hide_label其中hide_label用于隐藏字段标签inline用于让选项横向排列autofocus让控件获得页面焦点input_type决定input的 type 属性如password、email、number等。小结HTML 页面输出TemplateHTMLRenderer渲染 context 字典到指定模板StaticHTMLRenderer直接返回预渲染字符串模板名按Response → 渲染器类 → 视图方法 → 视图属性的优先级解析。HTML 表单输出render_form模板标签基于HTMLFormRenderer把序列化器渲染成表单绑定对象后自动填充初始值配合POSTredirect实现查看、更新与错误回显。模板包与字段样式内置vertical、horizontal、inline三个基于 Bootstrap 3 的模板包字段级通过style{base_template: ...}或style{template: ...}定制控件并可使用rows、placeholder、hide_label等附加选项。相关主题可继续阅读 Browsable API 指南了解horizontal表单在交互式 API 页面中的应用、Request 对象了解request.data如何驱动表单提交以及 序列化器指南了解字段校验与嵌套序列化器。【免费下载链接】django-rest-frameworkWeb APIs for Django. 项目地址: https://gitcode.com/gh_mirrors/dj/django-rest-framework创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网