Как получить доступ к данным в шаблоне при использовании DRF ModelViewSet и TemplateHTMLRenderer?
у меня есть фреймворк Django. остальное ModelViewSet
и пытаюсь использовать TemplateHTMLRenderer
для отображения HTML. Следование в учебник:
from rest_framework import permissions, renderers, viewsets
from rest_framework.decorators import link
from . import models, serializers
from .permissions import IsOwnerOrReadOnly
class SnippetViewSet(viewsets.ModelViewSet):
template_name = 'snippet-list.html'
queryset = models.Snippet.objects.all()
serializer_class = serializers.SnippetSerializer
renderer_classes = (renderers.TemplateHTMLRenderer,)
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
@link(renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
def pre_save(self, obj):
obj.owner = self.request.user
если я добавлю ключ в def resolve_context()
Я могу получить доступ к объектам модели в моем шаблоне, которые передаются в RequestContext
. Если я не добавлю data
ключ тогда я не знаю, как получить доступ к фрагментам.
def resolve_context(self, data, request, response):
if response.exception:
data['status_code'] = response.status_code
#return RequestContext(request, data) # original source on github
return RequestContext(request, {'data': data}) # if I add a key I can access it
так что я должен пропустить что-то легкое или как я ожидаю, что это будет вести себя не так как задумали авторы?
4 ответов
Я бы пошел в эту сторону:
class SnippetViewSet(viewsets.ModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
renderer_classes = (renderers.JSONRenderer, renderers.TemplateHTMLRenderer)
def list(self, request, *args, **kwargs):
response = super(SnippetViewSet, self).list(request, *args, **kwargs)
if request.accepted_renderer.format == 'html':
return Response({'data': response.data}, template_name='home.html')
return response
и использовать http://127.0.0.1:8000/snippets/.html
чтобы получить таблицу (или любой суффикс, который вы используете).
таким образом, вы не переопределяете распознаватель для каждого типа рендеринга.
другим решением было бы просто создать выделенное представление для действия списка и использовать только HTML-визуализатор. Но тогда у вас будет небольшое дублирование кода.
Я также встретил тот же вопрос с вами, и я тоже так думал. Я пришел сюда через Гугл. Мне не понравилось переопределять " Def list (self, request, *args, **kwargs):", потому что я чувствовал, что это сломало идею дизайна viewset. После того, как я исследовал учебник фрагмента и исходный код в "site-packages\rest_framework", я получил ключ, а не набор представлений, но "сериализатор.данные." В ...site-packages\rest_framework\serializers.py", я нашел класс BaseSerializer, то есть верхний базовый класс ModelSerializer. Свой свойство "data" определяется следующим образом:
@property
def data(self):
... # omitted the function body here, because it didn't care about this solution.
return self._data
эти данные свойств являются только "сериализатором".данные " это просто ответ, переданный шаблону. Поэтому я просто переопределил свойство data в "snippets/serializers.py", и после вызова метода отца, установите ключ для возвращаемых данных:
class SnippetSerializer(serializers.ModelSerializer):
@property
def data(self):
return { 'data' : super(serializers.ModelSerializer, self).data } #'data' can be replaced with other wanted name.
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
OK, используйте имя "данные" в вашем шаблоне.
Я подкласс и переопределил метод, который предоставляет контекст шаблона, так что данные сериализатора доступны в разделе data
в контексте шаблона:
from rest_framework.renderers import TemplateHTMLRenderer
class MyHTMLRenderer(TemplateHTMLRenderer):
def get_template_context(self, data, renderer_context):
context = {'data': data}
response = renderer_context['response']
if response.exception:
data['status_code'] = response.status_code
return context
внутри viewset использовать рендерер класс
renderer_classes = (рендереры.JSONRenderer, renderers.TemplateHTMLRenderer)
Как выше и переопределить ListModelMixinметод списка.
mariodev's ответ дает лучший пример также.