Django-rest-framework

一:创建数据模型

class Blog(models.Model):
    auth=models.CharField(max_length=50)
    # 字段自动为当前时间
    created = models.DateTimeField(auto_now_add=True)
    # blank=True:此字段可为空
    title = models.CharField(max_length=100, blank=True, default='')
    content = models.TextField()

    class Meta:
        ordering = ['created']

二:迁移数据库

python  manage.py makemigrations
python  manage.py migration

三:创建一个基于Serializer类的序列化器

from rest_framework import serializers

from rest_api.models import  Blog

"""
REST framework中的serializers与Django的Form和ModelForm类非常像。DRF提供了一个最底层最基础的Serializer类,它类似Django的Form类,为我们提供了强大的通用方法来控制响应的输出。
以及一个ModelSerializer类,类似Django的ModelForm类,为创建用于处理模型实例和查询集的序列化程序提供了快捷实现方式,但可自定义程度较低。
"""
#创建基于Serializer(比较处于底层,可定制化高)的序列化器类
#给models对象创建序列化器

class BlogSerializer(serializers.Serializer):
    #
    id = serializers.IntegerField(read_only=True)
    auth=serializers.CharField(max_length=50)
    title = serializers.CharField(required=False, allow_blank=True, max_length=100)
    # style用于控制显示序列化程序的风格
    content = serializers.CharField(style={'base_template': 'textarea.html'})
    
    def create(self, validated_data):
        # 返回django模型中对象对应的数据
        return Blog.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.auth = validated_data.get('auth', instance.auth)
        instance.title = validated_data.get('title', instance.title)
        instance.content= validated_data.get('content', instance.content)
        instance.save()
        return instance

四:进入Django shell

(IPFS_Django) appledeMac-mini-3:Api apple$ python manage.py shell
Python 3.7.5 (default, Oct 25 2019, 10:52:18) 
[Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from rest_api.models import Blog
>>> from rest_api.serializers import BlogSerializer
>>> from rest_framework.renderers  import JSONRenderer
>>> from rest_framework.parsers  import JSONParser
#给数据模型添加数据
>>> blog=Blog(auth='W',content='asimov is super')
>>> blog.save()
>>> blog=Blog(auth='M',content='hello  word')
>>> blog.save()
数据序列化:
>>> serializer=BlogSerialzer(blog)
>>> serializer.data
#本地python数据类型
{'id': 2, 'auth': 'M', 'title': '', 'content': 'hello  word'}
#渲染成成品json格式
>>> content=JSONRenderer().render(serializer.data)
>>> content
b'{"id":2,"auth":"M","title":"","content":"hello  word"}'

反序列化:

>>> import io
>>> stream=io.BytesIO(content)
#将二进制流数据转换成本地python数据类型
>>> data=JSONParser().parse(stream)
>>> data
{'id': 2, 'auth': 'M', 'title': '', 'content': 'hello  word'}
#本机数据类型完全还原到填充的对象实例中
>>> serializer=BlogSerializer(data=data)
#数据验证
>>> serializer.is_valid()
True
>>> serializer.validated_data
OrderedDict([('auth', 'M'), ('title', ''), ('content', 'hello  word')])
>>> serializer.save()
<Blog: Blog object (3)>


五:创建一个基于ModelSerializers类的序列化器

class Rest(serializers.ModelSerializer):
    """
    基于Serializer
    自动确定的一组字段。
    实现简单默认的create()和update()方法。需要高定制化的序列化器还是用Serializer类
    """
    class Meta:
        model = Blog
        fields = ['id', 'auth','title', 'content']

六:写基于@api_view装饰器的django_restframework视图函数

from django.http import JsonResponse, HttpResponse, Http404
from django.shortcuts import render

# Create your views here.

from django.views.decorators.csrf import csrf_exempt

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rest_framework.views import APIView

from rest_api.models import Blog
from rest_api.serializers import  Rest


# 基于ModelSerializer序列化器的视图
#@csrf_exempt:取消CSRF令牌,或在settings中取消
#@csrf_exempt


#基于功能视图

#该@api_view装饰与基于功能视图工作。限制请求方式
@api_view(['GET','POST'])

#API的根源将是一个视图,该视图支持列出所有现有的代码片段或创建新的代码片段。
def rest_list(request):
    """
    REST框架引入了一个Request对象,该对象扩展了normal HttpRequest,
    并提供了更灵活的请求解析。Request对象的核心功能是request.data属性,该属性与相似request.POST

    REST框架还引入了一个Response对象,该对象采用TemplateResponse呈现的内容
    :param request:
    :return:
    """
    if request.method == 'GET':
        # 取出数据库中数据
        rest_api = Blog.objects.all()
        # 生成序列化查询集:数据,序列化器参数中添加一个标志many=True
        serializer = Rest(rest_api, many=True)
        #返回json数据
        #return JsonResponse(serializer.data, safe=False)#--->用Response代替
        return Response(serializer.data)
    elif request.method == 'POST':
        #处理request请求的数据:将一个bytes流解析为Python原生的数据类型-->{'':''}
        #data = JSONParser().parse(request)------>用request.data代替
        # Rest:使用基于ModelSerializer序列化器
        #将Python原生的数据类型字典,反序列化
        serializer = Rest(data=request.data)
        #数据验证
        if serializer.is_valid():
            #保存数据
            serializer.save()
            #rest_framework中的状态码
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

#@csrf_exempt
@api_view(['GET','PUT','DELETE'])

#单个代码段相对应的视图,该视图可用于检索,更新或删除该代码段。
def rest_detail(request,pk):
    try:
        rest = Blog.objects.get(pk=pk)
    except  Blog.DoesNotExist:
        #return HttpResponse(status=status.HTTP_404_NOT_FOUND)
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = Rest(rest)
        return Response(serializer.data)
    elif request.method == 'PUT':
        #data = JSONParser().parse(request)
        serializer = Rest(rest, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'DELETE':
        rest.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

1.return JsonResponse()
在这里插入图片描述
2.return Response() :该对象采用TemplateResponse呈现的内容
在这里插入图片描述
在这里插入图片描述
3.put
在这里插入图片描述
根url:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('rest_api.urls'))
]

app_url

from django.urls import path

from rest_api import views

urlpatterns=[
    path('rest_list/',views.rest_list),
    path('rest_list/<int:pk>/',views.rest_detail)
]

**七:基于APIview类的视图:**

class   rest_list1(APIView):
    def get(self,request,format=None):
        rest=Blog.objects.all()
        serializer=Rest(rest,many=True)
        return Response(serializer.data)

    def post(self,request,formar=None):
        serializer=Rest(data=request.data)
        if  serializer.is_valid():
            serializer.save()
            return Response(serializer.data,status=status.HTTP_201_CREATED)
        return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)


class rest_detail1(APIView):
    # 获取数据库中的数据,即models中的数据
    def get_object(self, pk):
        try:
            return Blog.objects.get(pk=pk)
        except   Blog.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        # 通过pk获取对应的数据
        rest = self.get_object(pk)
        # 通过Rest序列化器进行数据序列化
        serializer = Rest(rest)
        # 返回json数据
        return Response(serializer.data)
    def put(self,request,pk,format=None):
        rest=self.get_object(pk)
        serializer=Rest(rest)
        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,format=None):
        rest=self.get_object(pk)
        rest.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

url配置

   path('rest_list1/', views.rest_list1.as_view()),
    path('rest_list1/<int:pk>/', views.rest_detail1.as_view())

八:REST框架的generics和mixins类

from rest_framework import mixins
from rest_framework import generics


class Restlist(mixins.ListModelMixin,
               mixins.CreateModelMixin,
               generics.GenericAPIView):
    """
    构建GenericAPIView类的视图,并添加mixins.ListModelMixin,mixins.CreateModelMixin
    1.GenericAPIView:基类提供核心功能
    2。minxins:提供list()和create()方法
    """

    queryset = Blog.objects.all()
    # 序列化器类
    serializer_class = Rest

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class RestDetail(mixins.RetrieveModelMixin,
                 mixins.UpdateModelMixin,
                 mixins.DestroyModelMixin,
                 generics.GenericAPIView):
    """
    基于基类generics,提供.retrieve(),.update(),.destroy()方法
    """
    queryset = Blog.objects.all()
    serializer_class = Rest

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

在这里插入图片描述
REST框架提供了一组混合的通用视图(generics,mixins),写views更简单

class   Restlist1(generics.ListCreateAPIView):
    queryset = Blog.objects.all()
    serializer_class = Rest
    
class   RestDetail1(generics.RetrieveUpdateDestroyAPIView):
    queryset = Blog.objects.all()
    serializer_class = Rest

九:身份验证和权限
1.给models.py中Blog添加所属作者,此处用django后台的user比较方便(所以把之前auth当字段)

class Blog(models.Model):
    auth=models.CharField(max_length=50)
    # 字段自动为当前时间
    created = models.DateTimeField(auto_now_add=True)
    # blank=True:此字段可为空
    title = models.CharField(max_length=100, blank=True, default='')
    content = models.TextField()
    #作为外键关联django后台的auth.User
	owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)

2.更新数据模型:

更新模型数据库的时候可能不行,因为加外键了,建议重新建个数据库

3.写User序列化器

from django.contrib.auth.models import User


class UserSerializer(serializers.ModelSerializer):
    #因为user是通过外键和Blog表连接的,ModelSerializer此处默认情况下不包含此关系
    rests = serializers.PrimaryKeyRelatedField(many=True, queryset=Blog.objects.all())

    class Meta:
        model = User
        #所以做一个显式字段rests将user和blog关联起来
        fields = ['id', 'username', 'rests']

4.更新Blog模型的序列化器Rest

class Rest(serializers.ModelSerializer):
    """
    基于Serializer
    自动确定的一组字段。
    实现简单默认的create()和update()方法。需要高定制化的序列化器还是用Serializer类
    """
    #ReadOnlyField:这个字段只读,不能修改
    #source:将用于填充字段的属性的名称。可以是仅接受self参数的方法,
    #用于串行交涉,但不会被用于更新模型反序列化的实例
    owner = serializers.ReadOnlyField(source='owner.username')
    class Meta:
        model = Blog
        fields = ['id','auth','title', 'content','owner']

5.给视图加权限:

from rest_framework import permissions

# Rest提供了基类generics和mixins类的混合用法
class Restlist1(generics.ListCreateAPIView):
	#验证过的操作或者只读
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    queryset = Blog.objects.all()
    serializer_class = Rest
    #将Blog与用户相关联
    #现在create(),我们的序列化器方法将被传递一个附加'owner'字段,以及来自请求的验证数据
    def perform_create(self, serializer):
        # #修改实例保存,处理请求中的owner信息
        serializer.save(owner=self.request.user)

class RestDetail1(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    queryset = Blog.objects.all()
    serializer_class = Rest

查看效果:只能读

在这里插入图片描述
6.添加登陆/登出功能:django-rest-framework帮我们实现了API的浏览login/logout功能,
也可以自己搞

在这里插入图片描述

在根urls添加 path(‘auth/’,include(‘rest_framework.urls’))

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('rest_api.urls')),

    path('auth/',include('rest_framework.urls'))
]

7.登陆(刷新后右上角会出现登陆入口)并修改api内容
在这里插入图片描述

十:对象级别权限
1.在app目录下写一个permissions.py的

from rest_framework import permissions


class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    def has_object_permission(self, request, view, obj):

        #Return `True` if permission is granted, `False` otherwise.

        return True


    SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
    """

    def has_object_permission(self, request, view, obj):
        #如果是('GET', 'HEAD', 'OPTIONS')请求则返回 True
        if request.method in permissions.SAFE_METHODS:
            return True
        #obj.owner是写这个Blog内容的作者
        #返回 Bool(obj.owner是否等于请求时的user)
        return obj.owner == request.user

2.给对象(Restlist1/下的单个实例)加权限:只允许作者本人操作自己的博客

from rest_api.permissions import IsOwnerOrReadOnly


# permission_classes = [permissions.IsAuthenticatedOrReadOnly]
class RestDetail1(generics.RetrieveUpdateDestroyAPIView):
    # permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    # 添加对象验证
    # IsOwnerOrReadOnly返回的是bool类型

    #1。满足登陆用户 and  2。满足blog对应user,才能对blog操作
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
    queryset = Blog.objects.all()
    serializer_class = Rest

查看效果:
在这里插入图片描述

在这里插入图片描述

十一:API​​进行身份验证

可以使用token对用户访问api进行验证

十二:ModelSerializer的升级版HyperlinkedModelSerializer:超链接

使用超链接建立关系来提高API的内聚性和可发现性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值