【问题标题】:Django rest framework: serializers.ReadOnlyField() doesn't display field in browsable apiDjango rest 框架:serializers.ReadOnlyField() 不在可浏览 api 中显示字段
【发布时间】:2016-04-04 07:38:40
【问题描述】:

Django rest 框架:如何在可浏览的 api 中显示只读字段?

当我将result = serializers.CharField(read_only=True) 添加到我的模型序列化程序时,表单不再呈现结果字段。

我理解用户删除表单输入上的disabled 属性的安全问题(虽然我很惊讶 django 本身不处理这个),所以我如何在 api.html 中实现只读字段来自result的模板?

序列化器.py

class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
result = serializers.CharField(read_only=True)

class Meta:
    model = Snippet
    fields = ('title', 'code', 'owner', 'url', 'result')

我是 django-rest 框架的新手,因此我们将不胜感激!

【问题讨论】:

    标签: python django rest serialization django-rest-framework


    【解决方案1】:

    你有两个选择:

    1. 要么在模型中计算结果

    2. 或者在序列化中添加字段

    您选择什么取决于您是否想在其他地方使用该计算结果以及您是否可以触摸模型。

    当你想在模型中计算结果时

    按照 Django 的派生全名的示例,在某处: https://github.com/django/django/blob/master/django/contrib/auth/models.py#L348

    或在文档中解释:https://docs.djangoproject.com/en/dev/topics/db/models/#model-methods

    这将自动充当 DRF 的只读字段。

    你可以在下面的代码中看到用法(get_full_name)。

    当你想在序列化中添加字段时

    您可以在 DRF 文档中找到答案:http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

    SerializerMethodField 这是一个只读字段...可用于将任何类型的数据添加到对象的序列化表示中。

    serializers.py 中的 hours_since_joined 示例:

    from django.contrib.auth.models import User, Group
    from rest_framework import serializers
    from django.utils.timezone import now
    
    class UserSerializer(serializers.HyperlinkedModelSerializer):
        hours_since_joined = serializers.SerializerMethodField()
        class Meta:
            model = User
            fields = ('url', 'username', 'email', 'groups', 'hours_since_joined', 'first_name', 'last_name', 'get_full_name' )
    
        def get_hours_since_joined(self, obj):
            return (now() - obj.date_joined).total_seconds() // 3600
    
    class GroupSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = Group
            fields = ('url', 'name', 'user_set')
    

    对于您的情况:

    class SnippetSerializer(serializers.HyperlinkedModelSerializer):
        owner = serializers.ReadOnlyField(source='owner.username')
        result = serializers.SerializerMethodField()
    
        class Meta:
            model = Snippet
            fields = ('title', 'code', 'owner', 'url', 'result')
    
        def get_result(self, obj):
            # code here to calculate the result
            # or return obj.calc_result() if you have that calculation in the model
            return "some result"
    

    在 DRF 的可浏览 API 中显示添加的字段

    您需要在 Meta 的字段中列出它们 - 参见上面的示例。这将在请求的可浏览输出中显示。但是它不会在 DRF 的 HTML 表单中显示它们。原因是HTML表单只用于提交信息,所以restframework模板在渲染时跳过了只读字段。

    如您所见,加入后的全名和小时数并未呈现在表单中,但可用于 API:

    如果您想在表单上也显示只读字段

    您需要覆盖 restframework 模板。

    • 确保您的模板在 restframework 之前加载(即您的应用在 settings.py 中的 restframework 之上)
    • 使用应用下的模板目录
    • 在模板目录中创建子目录:restframework/horizo​​ntal
    • 从 Python 的 Lib\site-packages\rest_framework\templates\rest_framework\horizo​​ntal\ 中复制 form.html 和 input.html

    • 更改form.html

    {% load rest_framework %}
    {% for field in form %}
        {% render_field field style=style %}
    {% endfor %}
    
    • 更改 input.html 中的输入行(添加禁用属性)

      <input name="{{ field.name }}"  {% if field.read_only %}disabled{% endif %} {% if style.input_type != "file" %}class="form-control"{% endif %} type="{{ style.input_type }}" {% if style.placeholder %}placeholder="{{ style.placeholder }}"{% endif %} {% if field.value %}value="{{ field.value }}"{% endif %}>
      

    结果:

    【讨论】:

    • 嗯 - 我仍然没有在可浏览的 api 版本中看到结果。我可以编辑代码和标题字段,但我还想显示结果(只读)
    • 从命令行测试 api - 我可以看到结果,所以我认为这是一个模板问题? { "code": "sdfsdfsdfddd", "owner": "testuser", "result": "some result", "title": "dummy", "url": "localhost/data/snippets/26" }
    • 您的意思是,您在可浏览的 API 输出中看不到它吗?还是在 HTML 表单中?
    • 两者。我假设我需要将值放入模板中,但我不确定如何做到这一点。
    • 更新了答案以查看可浏览 API 的结果。 (添加到字段)。我认为您不会将其放入表单中,因为该表单用于可写字段。
    【解决方案2】:

    对于无法在 Browsable API 中显示的人,模板文件夹应命名为:rest_framework

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-22
      • 2021-02-23
      • 2020-07-15
      • 2017-02-03
      • 2016-06-06
      • 1970-01-01
      • 2021-06-30
      • 2020-06-26
      相关资源
      最近更新 更多