教程来源杜塞-django-vue系列
博客链接 传送门
传统Django中就有基于类的试图存在,DRF 中自然也有,功能大致相同。
在视图函数中新增以下代码:
# article/views.py
from rest_framework.views import APIView
from django.http import Http404
class ArticleDetail(APIView):
"""文章详情试图"""
def get_object(self, pk):
try:
# pk为文章主键,默认为id
return Article.objects.get(pk=pk)
except:
raise Http404
def get(self, request, pk):
article = self.get_object(pk)
serializer = ArticleListSerializer(article)
# 返回 Json 数据
return Response(serializer.data)
def put(self, request, pk):
article = self.get_object(pk)
serializer = ArticleDetailSerializer(article,data=request.data)
# 验证合法性,不合法返回400
if serializer.is_valid():
# 序列化器将持有的数据反序列化后存入数据库
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
article = self.get_object(pk)
article.delete()
# 删除后返回204
return Response(status=status.HTTP_204_NO_CONTENT)
代码不复杂,就是提供了对文章详情的获取、修改、删除的 3 个方法,以及 1 个用于获取单个文章 model 的辅助方法。和之前说的一样,DRF 类视图与传统 Django 的区别,.get()
、 .put()
就是多了一个将对象序列化(或反序列化)的步骤。.delete() 方法因为不用返回实际数据,执行完删除动作就OK了。
由于详情接口需要返回完整的字段数据,所以要重新给它定义一个序列化器:
class ArticleDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
pythonfields = '__all__'
代表要使用所有字段。
配置article/url.py:
urlpatterns = [
···
path('<int:pk>/', ArticleDetail.as_view(), name='detail'),
]
这就可以了。
发送一个请求试试:
(venv) E:\drf>http http://127.0.0.1:8000/api/article/1/
HTTP/1.1 200 OK
Allow: GET, PUT, DELETE, HEAD, OPTIONS
Content-Length: 158
Content-Type: application/json
Date: Sat, 12 Jun 2021 12:47:22 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"body": "Python is one of my favorite programming languages",
"created": "2021-06-11T11:35:50Z",
"id": 1,
"title": "python",
"updated": "2021-06-11T11:37:14.001883Z"
}
使用 PUT 添加文章试试:
(venv) E:\drf>http PUT http://127.0.0.1:8000/api/article/1/ title=something.. body=changed..
HTTP/1.1 200 OK
Allow: GET, PUT, DELETE, HEAD, OPTIONS
Content-Length: 122
Content-Type: application/json
Date: Sat, 12 Jun 2021 12:52:23 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"body": "changed..",
"created": "2021-06-11T11:35:50Z",
"id": 1,
"title": "something..",
"updated": "2021-06-12T12:52:23.905435Z"
}
然后删除掉:
(venv) E:\drf>http delete http://127.0.0.1:8000/api/article/1/
HTTP/1.1 204 No Content
Allow: GET, PUT, DELETE, HEAD, OPTIONS
Content-Length: 0
Date: Sat, 12 Jun 2021 12:54:07 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
这篇id=1
的文章就被删除掉了。注意:put delete 大小写均可以。
通用试图-简化代码
对数据的增删改查我们可以不用使用繁杂的操作,可以通过 DRF 提供的 Mixin 类直接集成对应的功能。
修改一下 ArticleDetail
视图:
# article/views.py
from rest_framework import mixins
from rest_framework import generics
class ArticleDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
"""文章详情试图"""
queryset = Article.objects.all()
serializer_class = ArticleDetailSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
使用Mixin 已经组合够简单了,但我们还可以更简单:
# article/views.py
# 文章试图
class ArticleList(generics.ListCreateAPIView):
queryset = Article.objects.all()
serializer_class = ArticleDetailSerializer
# 列表视图也可以这样更改
class ArticleDetail(generics.RetrieveUpdateDestroyAPIView):
"""文章详情试图"""
queryset = Article.objects.all()
serializer_class = ArticleDetailSerializer
列表测试:
(venv) E:\drf>http http://127.0.0.1:8000/api/article/
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 352
Content-Type: application/json
Date: Sat, 12 Jun 2021 13:05:38 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
[
{
"body": "I like too。",
"created": "2021-06-11T11:37:15Z",
"id": 2,
"title": "Java",
"updated": "2021-06-11T11:37:31.117904Z"
},
{
"body": "I'm testing",
"created": "2021-06-11T11:37:34Z",
"id": 3,
"title": "test",
"updated": "2021-06-11T11:37:56.285260Z"
},
{
"body": "",
"created": "2021-06-11T14:34:28.022152Z",
"id": 4,
"title": "c++",
"updated": "2021-06-11T14:34:28.022152Z"
}
]
文章详情页测试:
查看
(venv) E:\drf>http http://127.0.0.1:8000/api/article/2/
HTTP/1.1 200 OK
Content-Length: 119
Content-Type: application/json
{
"body": "I like too。",
"created": "2021-06-11T11:37:15Z",
"id": 2,
"title": "Java",
"updated": "2021-06-11T11:37:31.117904Z"
}
修改
(venv) E:\drf>http put http://127.0.0.1:8000/api/article/2/ title=test body=changed..
HTTP/1.1 200 OK
Content-Length: 115
Content-Type: application/json
{
"body": "changed..",
"created": "2021-06-11T11:37:15Z",
"id": 2,
"title": "test",
"updated": "2021-06-12T13:07:26.031985Z"
}
删除
(venv) E:\drf>http delete http://127.0.0.1:8000/api/article/2/
HTTP/1.1 204 No Content
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 0
Date: Sat, 12 Jun 2021 13:07:56 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
均测试成功,除了上述介绍的以外,框架还提供 ListModelMixin
、CreateModelMixin
等混入类或通用视图,覆盖了基础的增删改查需求。