2017-11-19 24 views
1

Django RESTフレームワークを初めて使用しています。私がやろうとしているのは、ブラウズ可能なAPIでViewSetが自動的にレンダリングされる方法と同様に、HTMLでGeneric APIView(RetrieveUpdateDestroyAPIView)をレンダリングすることです。Django RESTフレームワーク:HTMLレンダリング汎用APIView

公式documentation後、私は私のて、myApp/views.pyで持っている:

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,) 

urls.pyで:

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<pk>[0-9]+)/$', views.AnnounceDetail.as_view(), name='announce-detail'), 

私はブラウズ可能APIを行くとき、 link/api/announces/3 /を介して、認証されたユーザーに応じて適切なアクセス許可を使ってannounceオブジェクトを正しく見ることができます。私はよく理解していれば

{% load rest_framework %} 

{% block content %} 

<form action="{% url 'announce-detail' pk=announce.pk %}" method="POST"> 
    {% csrf_token %} 
    {% render_form serializer %} 
    <input type="submit" value="Save"> 
</form> 

{% endblock content %} 

、:ここで

NoReverseMatch at /announces/3/ 

Reverse for 'announce-detail' with keyword arguments '{'pk': ''}' not found. 3 pattern(s) tried: ['announces/(?P<pk>[0-9]+)/$', 'api/announces/(?P<pk>[^/.]+)\\.(?P<format>[a-z0-9]+)/?$', 'api/announces/(?P<pk>[^/.]+)/$'] 

は私のannounce_detail.htmlテンプレートです:

しかし、私は/に行き、私はこのエラーを持って、/ 3 /を発表しますDjangoのRESTビュー(ViewSetまたはViewAPI)はJSON形式でデータを取得/配置するためのもので、Djangoの通常ビューはHTMLの通常のレンダリング用です。しかし、Django REST Viewは通常のDjango HTMLレンダリングにも使用できます。公開されたAPIエンドポイントを持つことで、他のアプリケーション(同じWebアプリケーションやその他のWebアプリケーション/モバイルアプリなど)でデータを取得して使用することができます。私が間違っているなら、私を訂正してください。

なぜ私はエラーが発生したのか分かりません... ありがとうございました!

UPDATE 通常APIViewを作成した後、私は彼/彼女がいないときに、ユーザは、[保存]ボタンをクリックしようとすると、ステータス403は、禁止(フォームがレンダリングされますし、管理、および権限は尊敬されますしかし、それでもフィールドは「変更可能」として表示されます。つまり、領域内にテキストを入力できますが、変更を行うオーナーでない場合は[保存]ボタンでデータを保存しません。

myApp/views.py

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 

答えて

2

views.py

from django.shortcuts import get_object_or_404 
from rest_framework.response import Response 

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,) 

    def retrieve(self, request, pk, *args, **kwargs): 
     announce = get_object_or_404(Announce, pk=pk) 
     serializer = get_serializer(announce) 
     return Response({'serializer': serializer, 'announce': announce}) 

announce_detail.html

{% load rest_framework %} 
{% load staticfiles %} 

{% block content %} 

<form action="{% url 'announce-detail' pk=announce.pk %}" data-method="PUT"> 
    {% csrf_token %} 
    {% render_form serializer %} 
    <input type="submit" value="Save"> 
</form> 

{% endblock content %} 

<script> 
    window.drf = { 
     csrfHeaderName: "X-CSRFTOKEN", 
     csrfCookieName: "csrftoken" 
    }; 
</script> 
<script src="{% static 'rest_framework/js/jquery-1.12.4.min.js' %}"></script> 
<script src="{% static 'rest_framework/js/ajax-form.js' %}"></script> 
<script src="{% static 'rest_framework/js/csrf.js' %}"></script> 
<script src="{% static 'rest_framework/js/bootstrap.min.js' %}"></script> 
<script src="{% static 'rest_framework/js/prettify-min.js' %}"></script> 
<script src="{% static 'rest_framework/js/default.js' %}"></script> 
<script> 
    $(document).ready(function() { 
     $('form').ajaxForm(); 
    }); 
</script> 
+0

は、あなたの答えをありがとう! しかし、これはフォームをレンダリングしますが、ボタン 'Save'がクリックされると、 '405 Method Not Allowed'が表示されます。さらに、アナウンスではない場合でも、すべてのユーザーは(POSTが機能しなくても)「変更可能な」フォームを見ることができます。私が望むのは、Browsable APIとまったく同じバージョンです(つまり、Announceの所有者だけがフィールドを変更できます)が、HTMLテンプレートでレンダリングされます。 – filipyoo

+0

答えを更新しました。テンプレート(announce_detail.html)を追加しました。もう一度確認できますか? – origamic

+0

答えをありがとう! しかし、まだ動作しません。保存ボタンをクリックしても実際には何も行われません。入力領域を変更前の値にリフレッシュするだけで、変更は保存されません。 私の質問が更新されましたので、ご確認ください。 – filipyoo

関連する問題