title: Django REST framework: HTML render Generic APIView
body: <p>I am new to Django REST Framework. What I try to do is to render a Generic APIView (RetrieveUpdateDestroyAPIView) in HTML similarly to the way the ViewSet is automatically rendered in the Browsable API.</p>
  
  <p>Following the official <a href="http://www.django-rest-framework.org/topics/html-and-forms/" rel="nofollow noreferrer">documentation</a>, I have in my myApp/<strong>views.py</strong>:</p>
  
  <pre><code>class AnnounceViewSet(viewsets.ModelViewSet):
      """
      API endpoint that allows announces to be viewed or edited.
      """
      queryset = Announce.objects.all()
      serializer_class = AnnounceSerializer
      permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                            IsOwnerOrReadOnly,)
  
  
      def perform_create(self, serializer): # without this, the POST request of the announce doesnt work
          serializer.save(owner=self.request.user)
  
  
  class AnnounceList(APIView):
      renderer_classes = [TemplateHTMLRenderer]
      template_name = 'myApp/announces_list.html'
      permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
  
      def get(self, request):
          queryset = Announce.objects.all()
          return Response({'announces': queryset})
  
  class AnnounceDetail(generics.RetrieveUpdateDestroyAPIView):
     queryset = Announce.objects.all()
     serializer_class = AnnounceSerializer
     renderer_classes = [TemplateHTMLRenderer]
     template_name = 'myApp/announce_detail.html'
     permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,)
  </code></pre>
  
  <p>In my <strong>urls.py</strong>:</p>
  
  <pre><code>from django.conf.urls import url, include
  from rest_framework import routers
  from myApp import views
  from django.contrib import admin
  
  
  router = routers.DefaultRouter()
  router.register(r'api/users', views.UserViewSet)
  router.register(r'api/groups', views.GroupViewSet)
  router.register(r'api/announces', views.AnnounceViewSet)
  
  # Wire up our API using automatic URL routing.
  # Additionally, we include login URLs for the browsable API.
  urlpatterns = [
      url(r'^admin/', admin.site.urls),
      url(r'', include('myApp.urls')),
      url(r'^', include(router.urls)),
      url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
      url(r'^accounts/', include('allauth.urls')),
      url(r'^announces/$', views.AnnounceList.as_view(), name='announces-list'),
      url(r'^announces/(?P&lt;pk&gt;[0-9]+)/$', views.AnnounceDetail.as_view(), name='announce-detail'),
  </code></pre>
  
  <p>When I go the Browsable API, through the link /api/announces/3/, I can see properly the announce object, with the right permissions depending on the authenticated user.</p>
  
  <p>But when I go to the /announces/3/, I have this error:</p>
  
  <pre><code>NoReverseMatch at /announces/3/
  
  Reverse for 'announce-detail' with keyword arguments '{'pk': ''}' not found. 3 pattern(s) tried: ['announces/(?P&lt;pk&gt;[0-9]+)/$', 'api/announces/(?P&lt;pk&gt;[^/.]+)\\.(?P&lt;format&gt;[a-z0-9]+)/?$', 'api/announces/(?P&lt;pk&gt;[^/.]+)/$']
  </code></pre>
  
  <p>Here is my <strong>announce_detail.html</strong> template:</p>
  
  <pre><code>{% load rest_framework %}
  
  {% block content %}
  
  &lt;form action="{% url 'announce-detail' pk=announce.pk %}" method="POST"&gt;
      {% csrf_token %}
      {% render_form serializer %}
      &lt;input type="submit" value="Save"&gt;
  &lt;/form&gt;
  
  {% endblock content %}
  </code></pre>
  
  <p>If I understand well, the Django REST View (be it ViewSet or ViewAPI) is for retrieving/putting data in JSON format, and the Django normal view is for HTML usual rendering. However, the Django REST View can also be used for normal Django HTML rendering. By having an exposed API endpoint, data could be retrieved and be used by other applications (the same web app or other web app/mobile app etc...). Correct me if I am wrong.</p>
  
  <p>I don't understand why I got the error...
  Thank you for your help!</p>
  
  <p><strong>UPDATE</strong>
  After creating a normal APIView, I manage to get the form rendered, and the permissions is well respected (status 403 Forbidden when a user tries to click on the Save button, when the he/she is not the owner. But still, the fields appeared as 'modifyable', ie, we can input text inside the area, but the Save button doesn't save the data if it's not the owner that does the modification.</p>
  
  <p>myApp/views.py</p>
  
  <pre><code>class AnnounceDetail(APIView):  
      renderer_classes = [TemplateHTMLRenderer]
      template_name = 'myApp/announce_detail.html'
      permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                            IsOwnerOrReadOnly,)
  
  
  
      def get(self, request, pk):
          announce = get_object_or_404(Announce, pk=pk)
          self.check_object_permissions(self.request, announce) # required for IsOwnerOrReadOnly to work fine see https://stackoverflow.com/questions/25554415/django-rest-framework-ignoring-my-isownerorreadonly-permissions
          serializer_context = {
              'request': Request(request),
          }
          serializer = AnnounceSerializer(announce, context=serializer_context)
          return Response({'serializer': serializer, 'announce': announce})
  
      def post(self, request, pk):
          announce = get_object_or_404(Announce, pk=pk)
          self.check_object_permissions(self.request, announce) # required for IsOwnerOrReadOnly to work fine see https://stackoverflow.com/questions/25554415/django-rest-framework-ignoring-my-isownerorreadonly-permissions
          serializer_context = {
              'request': Request(request),
          }
          serializer = AnnounceSerializer(announce, context=serializer_context, data=request.data)
          if not serializer.is_valid():
              return Response({'serializer': serializer, 'announce': announce})
          serializer.save()
          return HttpResponseRedirect(reverse('announces-list')) # redirect to URL that is associated with the name announces-list
  </code></pre>