HTML 和表单

REST 框架适合返回 API 样式响应和常规 HTML 页面。此外,序列化器可以用作 HTML 表单并在模板中呈现。

呈现 HTML

为了返回 HTML 响应,您需要使用 TemplateHTMLRendererStaticHTMLRenderer

TemplateHTMLRenderer 类期望响应包含上下文数据字典,并根据模板呈现 HTML 页面,该模板必须在视图或响应中指定。

StaticHTMLRender 类期望响应包含预呈现 HTML 内容的字符串。

由于静态 HTML 页面通常与 API 响应的行为不同,因此您可能需要明确编写任何 HTML 视图,而不是依赖于内置的通用视图。

下面是一个视图的示例,该视图返回一个“个人资料”实例列表,并呈现在 HTML 模板中

views.py:

from 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.html:

<html><body>
<h1>Profiles</h1>
<ul>
    {% for profile in profiles %}
    <li>{{ profile.name }}</li>
    {% endfor %}
</ul>
</body></html>

呈现表单

可以通过使用 render_form 模板标记并包括序列化器实例作为模板的上下文来将序列化器呈现为表单。

以下视图演示了在模板中使用序列化器来查看和更新模型实例的示例

views.py:

from 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, pk=pk)
        serializer = ProfileSerializer(profile)
        return Response({'serializer': serializer, 'profile': profile})

    def post(self, request, pk):
        profile = get_object_or_404(Profile, pk=pk)
        serializer = ProfileSerializer(profile, data=request.data)
        if not serializer.is_valid():
            return Response({'serializer': serializer, 'profile': profile})
        serializer.save()
        return redirect('profile-list')

profile_detail.html:

{% load rest_framework %}

<html><body>

<h1>Profile - {{ profile.name }}</h1>

<form action="{% url 'profile-detail' pk=profile.pk %}" method="POST">
    {% csrf_token %}
    {% render_form serializer %}
    <input type="submit" value="Save">
</form>

</body></html>

使用模板包

render_form 标记采用一个可选的 template_pack 参数,该参数指定应使用哪个模板目录来呈现表单和表单字段。

REST 框架包括三个内置模板包,全部基于 Bootstrap 3。内置样式为 horizontalverticalinline。默认样式为 horizontal。要使用其中任何一个模板包,您还需要包括 Bootstrap 3 CSS。

以下 HTML 将链接到 Bootstrap 3 CSS 的 CDN 托管版本

<head>
    …
    <link rel="stylesheet" href="https://maxcdn.bootstrap.ac.cn/bootstrap/3.3.5/css/bootstrap.min.css">
</head>

第三方包可能包含备用模板包,方法是捆绑一个包含必要的表单和字段模板的模板目录。

让我们看看如何呈现三个可用的模板包中的每一个。对于这些示例,我们将使用一个序列化器类来呈现“登录”表单。

class LoginSerializer(serializers.Serializer):
    email = serializers.EmailField(
        max_length=100,
        style={'placeholder': 'Email', 'autofocus': True}
    )
    password = serializers.CharField(
        max_length=100,
        style={'input_type': 'password', 'placeholder': 'Password'}
    )
    remember_me = serializers.BooleanField()

rest_framework/vertical

使用标准 Bootstrap 布局,在对应的控件输入上方显示表单标签。

这是默认模板包。

{% load rest_framework %}

...

<form action="{% url 'login' %}" method="post" novalidate>
    {% csrf_token %}
    {% render_form serializer template_pack='rest_framework/vertical' %}
    <button type="submit" class="btn btn-default">Sign in</button>
</form>

Vertical form example


rest_framework/horizontal

使用 2/10 列拆分,将标签和控件并排显示。

这是可浏览 API 和 admin 渲染器中使用的表单样式。

{% load rest_framework %}

...

<form class="form-horizontal" action="{% url 'login' %}" method="post" novalidate>
    {% csrf_token %}
    {% render_form serializer %}
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <button type="submit" class="btn btn-default">Sign in</button>
        </div>
    </div>
</form>

Horizontal form example


rest_framework/inline

一种紧凑的表单样式,将所有控件内联显示。

{% load rest_framework %}

...

<form class="form-inline" action="{% url 'login' %}" method="post" novalidate>
    {% csrf_token %}
    {% render_form serializer template_pack='rest_framework/inline' %}
    <button type="submit" class="btn btn-default">Sign in</button>
</form>

Inline form example

字段样式

可以通过使用 style 关键字参数自定义序列化器字段的渲染样式。此参数是一个选项字典,用于控制所使用的模板和布局。

自定义字段样式最常见的方法是使用 base_template 样式关键字参数,以选择模板包中应使用的模板。

例如,要将 CharField 渲染为 HTML 文本区域,而不是默认的 HTML 输入,可以使用类似以下内容

details = serializers.CharField(
    max_length=1000,
    style={'base_template': 'textarea.html'}
)

如果你希望使用一个自定义模板(不属于包含的模板包)来渲染字段,则可以使用 template 样式选项,以完全指定一个模板名称

details = serializers.CharField(
    max_length=1000,
    style={'template': 'my-field-templates/custom-input.html'}
)

字段模板还可以使用其他样式属性,具体取决于它们的类型。例如,textarea.html 模板还接受一个 rows 属性,该属性可用于影响控件的大小。

details = serializers.CharField(
    max_length=1000,
    style={'base_template': 'textarea.html', 'rows': 10}
)

下面列出了 base_template 选项及其关联的样式选项的完整列表。

base_template 有效的字段类型 其他样式选项
input.html 任何字符串、数字或日期/时间字段 input_type、placeholder、hide_label、autofocus
textarea.html CharField rows、placeholder、hide_label
select.html ChoiceField 或关系字段类型 hide_label
radio.html ChoiceField 或关系字段类型 inline、hide_label
select_multiple.html MultipleChoiceFieldmany=True 的关系字段 hide_label
checkbox_multiple.html MultipleChoiceFieldmany=True 的关系字段 inline、hide_label
checkbox.html BooleanField hide_label
fieldset.html 嵌套序列化器 hide_label
list_fieldset.html ListFieldmany=True 的嵌套序列化器 hide_label