fil*_*yoo 5 html python django rest django-rest-framework
我是 Django REST 框架的新手。我尝试做的是在 HTML 中呈现 Generic APIView (RetrieveUpdateDestroyAPIView),类似于在 Browsable API 中自动呈现 ViewSet 的方式。
按照官方文档,我在 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,)
Run Code Online (Sandbox Code Playgroud)
在我的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'),
Run Code Online (Sandbox Code Playgroud)
当我通过链接 /api/announces/3/ 使用可浏览 API 时,我可以正确地看到公告对象,并根据经过身份验证的用户获得正确的权限。
但是当我转到 /announces/3/ 时,出现以下错误:
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>[^/.]+)/$']
Run Code Online (Sandbox Code Playgroud)
这是我的announce_detail.html模板:
{% 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 %}
Run Code Online (Sandbox Code Playgroud)
如果我理解得很好,Django REST 视图(无论是 ViewSet 还是 ViewAPI)用于检索/放入 JSON 格式的数据,而 Django 普通视图用于 HTML 通常的渲染。但是,Django REST 视图也可用于正常的 Django HTML 渲染。通过公开 API 端点,其他应用程序(同一 Web 应用程序或其他 Web 应用程序/移动应用程序等)可以检索数据并使用数据。如果我错了请纠正我。
我不明白为什么我收到错误...谢谢您的帮助!
更新 创建正常的 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 /sf/ask/1788809081/
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 /sf/ask/1788809081/
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
Run Code Online (Sandbox Code Playgroud)
小智 2
视图.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 = self.get_serializer(announce) # typo fixed
return Response({'serializer': serializer, 'announce': announce})
Run Code Online (Sandbox Code Playgroud)
公告_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>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9067 次 |
| 最近记录: |