mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-08 06:14:47 +03:00
Merge 1bcb2bd088
into d738ad7ae6
This commit is contained in:
commit
3e074fc7f9
|
@ -26,10 +26,13 @@ from rest_framework.compat import (
|
|||
)
|
||||
from rest_framework.exceptions import ParseError
|
||||
from rest_framework.request import is_form_media_type, override_method
|
||||
from rest_framework.reverse import reverse
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.utils import encoders
|
||||
from rest_framework.utils import encoders, model_meta
|
||||
from rest_framework.utils.breadcrumbs import get_breadcrumbs
|
||||
from rest_framework.utils.field_mapping import ClassLookupDict
|
||||
from rest_framework.utils.field_mapping import (
|
||||
ClassLookupDict, get_detail_view_name
|
||||
)
|
||||
|
||||
|
||||
def zero_as_none(value):
|
||||
|
@ -729,10 +732,13 @@ class AdminRenderer(BrowsableAPIRenderer):
|
|||
|
||||
return ret
|
||||
|
||||
def get_context(self, data, accepted_media_type, renderer_context):
|
||||
def get_context(self, data, accepted_media_type, renderer_context, reverse_func=None):
|
||||
"""
|
||||
Render the HTML for the browsable API representation.
|
||||
"""
|
||||
if not reverse_func:
|
||||
reverse_func = reverse
|
||||
|
||||
context = super(AdminRenderer, self).get_context(
|
||||
data, accepted_media_type, renderer_context
|
||||
)
|
||||
|
@ -756,6 +762,31 @@ class AdminRenderer(BrowsableAPIRenderer):
|
|||
header = results
|
||||
style = 'detail'
|
||||
|
||||
if style == 'list' and results:
|
||||
serializer_class = getattr(context['view'], 'serializer_class', None)
|
||||
fields = getattr(serializer_class.Meta, 'fields', None)
|
||||
|
||||
if issubclass(serializer_class, serializers.ModelSerializer) and fields \
|
||||
and 'url' not in fields:
|
||||
request = context['request']
|
||||
|
||||
def add_url(item):
|
||||
info = model_meta.get_field_info(serializer_class.Meta.model)
|
||||
pk = None
|
||||
|
||||
for field_name, field in info.fields_and_pk.items():
|
||||
if field.primary_key and (field_name in item):
|
||||
pk = item[field_name]
|
||||
|
||||
if pk:
|
||||
view_name = get_detail_view_name(serializer_class.Meta.model)
|
||||
url = reverse_func(view_name, kwargs={'pk': pk}, request=request)
|
||||
item['url'] = url
|
||||
|
||||
return item
|
||||
|
||||
results = [add_url(result) for result in results]
|
||||
|
||||
columns = [key for key in header.keys() if key != 'url']
|
||||
details = [key for key in header.keys() if key != 'url']
|
||||
|
||||
|
|
|
@ -14,12 +14,14 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
from rest_framework import permissions, serializers, status
|
||||
from rest_framework.renderers import (
|
||||
BaseRenderer, BrowsableAPIRenderer, HTMLFormRenderer, JSONRenderer
|
||||
AdminRenderer, BaseRenderer, BrowsableAPIRenderer, HTMLFormRenderer,
|
||||
JSONRenderer
|
||||
)
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.test import APIRequestFactory
|
||||
from rest_framework.views import APIView
|
||||
from tests.utils import mock_reverse
|
||||
|
||||
DUMMYSTATUS = status.HTTP_200_OK
|
||||
DUMMYCONTENT = 'dummycontent'
|
||||
|
@ -42,6 +44,12 @@ class DummyTestModel(models.Model):
|
|||
name = models.CharField(max_length=42, default='')
|
||||
|
||||
|
||||
class DummySerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = DummyTestModel
|
||||
fields = ('pk', 'name',)
|
||||
|
||||
|
||||
class BasicRendererTests(TestCase):
|
||||
def test_expected_results(self):
|
||||
for value, renderer_cls, expected in expected_results:
|
||||
|
@ -103,6 +111,12 @@ class HTMLView1(APIView):
|
|||
def get(self, request, **kwargs):
|
||||
return Response('text')
|
||||
|
||||
|
||||
class AdminRendererView(APIView):
|
||||
renderer_classes = (AdminRenderer, JSONRenderer)
|
||||
serializer_class = DummySerializer
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
|
||||
url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
|
||||
|
@ -111,6 +125,7 @@ urlpatterns = [
|
|||
url(r'^html$', HTMLView.as_view()),
|
||||
url(r'^html1$', HTMLView1.as_view()),
|
||||
url(r'^empty$', EmptyGETView.as_view()),
|
||||
url(r'^admin_renderer$', AdminRendererView.as_view()),
|
||||
url(r'^api', include('rest_framework.urls', namespace='rest_framework'))
|
||||
]
|
||||
|
||||
|
@ -459,3 +474,19 @@ class TestHiddenFieldHTMLFormRenderer(TestCase):
|
|||
field = serializer['published']
|
||||
rendered = renderer.render_field(field, {})
|
||||
assert rendered == ''
|
||||
|
||||
|
||||
class TestAdminRenderer(TestCase):
|
||||
def test_admin_renderer_adds_url(self):
|
||||
"""AdminRenderer should add a URL to the results if they come from a ModelSerializer"""
|
||||
renderer = AdminRenderer()
|
||||
data = [OrderedDict([('pk', 1), ('name', 'dummyname')])]
|
||||
view = AdminRendererView()
|
||||
request = view.initialize_request(APIRequestFactory().request())
|
||||
context = {'view': view, 'request': request,
|
||||
'response': view.as_view()(request)}
|
||||
|
||||
rendered_context = renderer.get_context(data, 'text/html', context, reverse_func=mock_reverse)
|
||||
|
||||
results = rendered_context['results'][0]
|
||||
assert results['url'] == 'http://example.org/dummytestmodel-detail/1/'
|
||||
|
|
Loading…
Reference in New Issue
Block a user