Repository: encode/django-rest-framework

Issue:
Docs crash when a viewset is called `data`
## Checklist

- [x] I have verified that that issue exists against the `master` branch of Django REST framework. (Commit 71ad99e0b276a90d055)
- [x] I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
- [x] This is not a usage question. (Those should be directed to the [discussion group](https://groups.google.com/forum/#!forum/django-rest-framework) instead.)
- [x] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](http://www.django-rest-framework.org/topics/third-party-resources/#about-third-party-packages) where possible.)
- [x] I have reduced the issue to the simplest possible case.
- [ ] I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)

## Steps to reproduce

* Register a viewset with the name `data` to a router. (`router.register('data', SomeViewSet)`)
* Navigate to the generated API docs page (as included by `include_docs_urls()`)

👉  See a minimal test repo here: https://github.com/akx/drf-docs-fail

## Expected behavior

The docs work as usual.

## Actual behavior

Docs crash with 

> *AttributeError*: 'Link' object has no attribute 'links'
> in djangorestframework/rest_framework/templatetags/rest_framework.py
> / schema_links, line 253

## Workaround

Don't name a viewset `data`.

(However, this isn't an acceptable workaround in my project, since the viewset literally concerns bits of data, and any other name would be worse.)


Discussion:
This'll need the same fix as #4972 (Fancy doing a PR?)

Thanks of the report! 
Mmm, if I understand correctly, this would require a `data` filter (to make it possible to reference the `data` attribute as opposed to Django's implicit `['data']`)?
If that is the case, would it maybe be better to write a generic `attr` filter?

```django
{% for link in document|attr:data|items %}...{% endfor %}
```
Yep. Sounds good. 

Resolving patch:
diff --git a/rest_framework/templatetags/rest_framework.py b/rest_framework/templatetags/rest_framework.py
--- a/rest_framework/templatetags/rest_framework.py
+++ b/rest_framework/templatetags/rest_framework.py
@@ -245,6 +245,20 @@ def items(value):
     return value.items()
 
 
+@register.filter
+def data(value):
+    """
+    Simple filter to access `data` attribute of object,
+    specifically coreapi.Document.
+
+    As per `items` filter above, allows accessing `document.data` when
+    Document contains Link keyed-at "data".
+
+    See issue #5395
+    """
+    return value.data
+
+
 @register.filter
 def schema_links(section, sec_key=None):
     """


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -26,6 +26,9 @@ def pytest_configure():
             {
                 'BACKEND': 'django.template.backends.django.DjangoTemplates',
                 'APP_DIRS': True,
+                'OPTIONS': {
+                    "debug": True,  # We want template errors to raise
+                }
             },
         ],
         MIDDLEWARE=MIDDLEWARE,
diff --git a/tests/test_renderers.py b/tests/test_renderers.py
--- a/tests/test_renderers.py
+++ b/tests/test_renderers.py
@@ -14,9 +14,10 @@
 from django.utils.safestring import SafeText
 from django.utils.translation import ugettext_lazy as _
 
+import coreapi
 from rest_framework import permissions, serializers, status
 from rest_framework.renderers import (
-    AdminRenderer, BaseRenderer, BrowsableAPIRenderer,
+    AdminRenderer, BaseRenderer, BrowsableAPIRenderer, DocumentationRenderer,
     HTMLFormRenderer, JSONRenderer, StaticHTMLRenderer
 )
 from rest_framework.request import Request
@@ -706,3 +707,32 @@ def get(self, request):
         response = view(request)
         response.render()
         self.assertInHTML('<tr><th>Iteritems</th><td>a string</td></tr>', str(response.content))
+
+
+class TestDocumentationRenderer(TestCase):
+
+    def test_document_with_link_named_data(self):
+        """
+        Ref #5395: Doc's `document.data` would fail with a Link named "data".
+            As per #4972, use templatetag instead.
+        """
+        document = coreapi.Document(
+            title='Data Endpoint API',
+            url='https://api.example.org/',
+            content={
+                'data': coreapi.Link(
+                    url='/data/',
+                    action='get',
+                    fields=[],
+                    description='Return data.'
+                )
+            }
+        )
+
+        factory = APIRequestFactory()
+        request = factory.get('/')
+
+        renderer = DocumentationRenderer()
+
+        html = renderer.render(document, accepted_media_type="text/html", renderer_context={"request": request})
+        assert '<h1>Data Endpoint API</h1>' in html
diff --git a/tests/urls.py b/tests/urls.py
--- a/tests/urls.py
+++ b/tests/urls.py
@@ -1,4 +1,11 @@
 """
-Blank URLConf just to keep the test suite happy
+URLConf for test suite.
+
+We need only the docs urls for DocumentationRenderer tests.
 """
-urlpatterns = []
+from django.conf.urls import url
+from rest_framework.documentation import include_docs_urls
+
+urlpatterns = [
+    url(r'^docs/', include_docs_urls(title='Test Suite API')),
+]