Фреймворк отдыха Django: serializers.ReadOnlyField() не отображает поле в доступных для просмотра API
Среда отдыха Django: Как я могу отобразить поле только для чтения в доступном для просмотра API?
Когда я добавлю result = serializers.CharField(read_only=True)
для моего сериализатора модели форма больше не отображает поле результатов.
Я понимаю проблемы безопасности пользователя, удаляющего disabled
атрибут на входе формы (хотя я удивлен, что django не обрабатывает это изначально), так как я могу реализовать поле только для чтения в шаблоне api.html из result
?
serializers.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 Framework, поэтому любая помощь будет оценена!
1 ответ
У вас есть 2 варианта:
либо рассчитать результат в модели
или добавить поле в сериализации
То, что вы выберете, зависит от того, хотите ли вы использовать этот вычисленный результат где-то еще и можете ли вы касаться моделей.
Когда вы хотите рассчитать результат в модели
Следуйте примеру полученного полного имени Джанго, где-то рядом: https://github.com/django/django/blob/master/django/contrib/auth/models.py
Или объясните здесь в документе: https://docs.djangoproject.com/en/dev/topics/db/models/
Это будет действовать как поле только для чтения для DRF автоматически.
Вы можете увидеть использование в коде ниже (get_full_name).
Когда вы хотите добавить поле в сериализации
У вас есть ответ в документации DRF: http://www.django-rest-framework.org/api-guide/fields/
SerializerMethodField Это поле только для чтения... Его можно использовать для добавления любых данных в сериализованное представление вашего объекта.
Пример hours_since_joined в serializers.py:
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"
Чтобы показать добавленные поля в браузере API DRF
Вы должны перечислить их в полях Меты - см. Пример выше. Это представит, что в доступном для просмотра выводе по запросам. Однако он не будет отображать их в HTML-форме DRF. Причина в том, что форма HTML используется только для отправки информации, поэтому шаблон restframework пропускает поле только для чтения при рендеринге.
Как вы видите, полное имя и часы с момента присоединения не отображаются в форме, но доступны для API:
Если вы хотите отобразить поля только для чтения также на форме
вам нужно переопределить шаблоны restframework.
- убедитесь, что ваши шаблоны загружены до работы restframework (т.е. ваше приложение находится выше restframework в settings.py)
- используйте dir шаблонов под вашим приложением
- создать subdir в ваших шаблонах dir: restframework/ горизонтальный
скопируйте form.html и input.html из библиотеки Python \site-packages\rest_framework\templates\rest_framework\ Horizontal\
изменить 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 %}>
Результат:
Для людей, которые не могут сделать его видимым в Browsable API, папка шаблона должна быть названа:
rest_framework