djangorest框架是今天看的一个文档。
比较简单的是入门篇,
https://github.com/moocstudent/django-proj
这个呢就是根据入门篇来的代码,
其中比django原教程多的就是关于深入的rest框架的关键点使用。
from django.shortcuts import render
from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework import permissions
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer
# Rather than write multiple views we're grouping together all the common behavior into classes called ViewSets.
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
class GroupViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Group.objects.all()
serializer_class = GroupSerializer
permission_classes = [permissions.IsAuthenticated]
比如下面这里的ModelViewSet就是一个通用的restful接口组件,
from django.contrib.auth.models import User, Group
from rest_framework import serializers
# Notice that we're using hyperlinked relations in this case with HyperlinkedModelSerializer.
# You can also use primary key and various other relationships, but hyperlinking is good RESTful design.
class UserSerializer(serializers.HyperlinkedModelSerializer):
# meta data set
class Meta:
model = User
# custom fields
fields = ['url', 'username', 'email', 'groups']
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ['url', 'name']
再比如serializer序列化,这个序列化类在view层进行了指定。
最后接口的路由是通过urls配置的:
from django.urls import include, path
from rest_framework import routers
from tutorial.quickstart import views
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
整理也就是说前端请求过来之后通过urls找到相应接口路由,
再找到视图views,然后处理相关逻辑,而serializer类似一个处理单元。
在serializer中,原本配置比较多
from rest_framework import serializers
import snippets.models
class SnippetSerializer(serializers.ModelSerializer):
# id = serializers.IntegerField(read_only=True)
# title = serializers.CharField(required=False, allow_blank=True, max_length=100)
# code = serializers.CharField(style={'base_template': 'textarea.html'})
# linenos = serializers.BooleanField(required=False)
# language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
# style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
class Meta:
model = Snippet
fields = ['id','title','code','linenos','language','style']
# def create(self, validated_data):
# """
# Create and return a new `Snippet` instance, given the validated data.
# """
# return Snippet.objects.create(**validated_data)
#
# def update(self, instance, validated_data):
# """
# Update and return an existing `Snippet` instance, given the validated data.
# """
# instance.title = validated_data.get('title', instance.title)
# instance.code = validated_data.get('code', instance.code)
# instance.linenos = validated_data.get('linenos', instance.linenos)
# instance.language = validated_data.get('language', instance.language)
# instance.style = validated_data.get('style', instance.style)
# instance.save()
# return instance
如果上面第一行是class SnippetSerializer(serializers.Serializer)的话对应注释代码也是
配合serializers.Serializer的,而ModelSerializer则提供了通用的方法。
好吧趁热打铁,执行python manage.py shell进入shell模式:
IPython 7.25.0 -- An enhanced Interactive Python. Type '?' for help.
...: from snippets.serializers import SnippetSerializer
...: from rest_framework.renderers import JSONRenderer
...: from rest_framework.parsers import JSONParser
...:
...: snippet = Snippet(code='foo = "bar"\n')
...: snippet.save()
...:
...: snippet = Snippet(code='print("hello, world")\n')
...: snippet.save()
In [2]: serializer = SnippetSerializer(snippet)
...: serializer.data
Out[2]: {'id': 2, 'title': '', 'code': 'print("hello, world")\n', 'linenos': False, 'language': 'python', 'style': 'friendly'}
In [3]: content = JSONRenderer().render(serializer.data)
...: content
Out[3]: b'{"id":2,"title":"","code":"print(\\"hello, world\\")\\n","linenos":false,"language":"python","style":"friendly"}'
In [4]: import io
...:
...: stream = io.BytesIO(content)
...: data = JSONParser().parse(stream)
In [5]: serializer = SnippetSerializer(data=data)
...: serializer.is_valid()
Out[5]: True
In [6]: serializer.validated_data
Out[6]:
OrderedDict([('title', ''),
('code', 'print("hello, world")'),
('linenos', False),
('language', 'python'),
('style', 'friendly')])
In [7]: serializer.save()
Out[7]: <Snippet: Snippet object (3)>
下载pip里的httpie请求查看:
HTTP/1.1 200 OK
Content-Length: 354
Content-Type: application/json
Date: Wed, 11 Jan 2023 12:36:47 GMT
Server: WSGIServer/0.2 CPython/3.9.9
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
[
{
"code": "foo = \"bar\"\n",
"id": 1,
"language": "python",
"linenos": false,
"style": "friendly",
"title": ""
},
{
"code": "print(\"hello, world\")\n",
"id": 2,
"language": "python",
"linenos": false,
"style": "friendly",
"title": ""
},
{
"code": "print(\"hello, world\")",
"id": 3,
"language": "python",
"linenos": false,
"style": "friendly",
"title": ""
}
]
同样的,如果请求有不同的url格式,django restframework也是支持的,
如:
http http://127.0.0.1:8000/snippets/ Accept:application/json # Request JSON
http http://127.0.0.1:8000/snippets/ Accept:text/html # Request HTML
http http://127.0.0.1:8000/snippets.json # JSON suffix
http http://127.0.0.1:8000/snippets.api # Browsable API suffix
而实现如上操作应该在接口定义format=None
@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk, format=None):
而None表示默认值。
同样在urls中加入format_suffix_patterns:
from django.urls import path
from snippets import views
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
path('snippets/', views.snippet_list),
path('snippets/<int:pk>/', views.snippet_detail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
在接口请求方面,django restframework提供了非常多的方式,
https://github.com/moocstudent/tutorial
比如RetrieveUpdateDestroyAPIView提供了获取一个数据详情,
更新以及删除的相关简便操作。
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics
"""
Using the mixin classes we've rewritten the views to use slightly less code than before,
but we can go one step further. REST framework provides a set of already mixed-in generic
views that we can use to trim down our views.py module even more.
"""
"""
List all code snippets, or create a new snippet.
"""
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
"""
Retrieve, update or delete a code snippet.
"""
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
作者:ukyo--3点买菜