DRF框架初步学习

参考:
https://www.cnblogs.com/xiaonq/p/10053234.html
http://www.cnblogs.com/wupeiqi/articles/7805382.html

什么是restful

1. REST与技术无关,代表的是一种软件架构风格(REST是Representational State Transfer的简称,中文翻译为“表征状态转移”)
2. REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识
3. 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
4. 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

restful规范设计

1、API与用户的通信协议,总是使用HTTPs协议。
  	2、域名 	
    1)子域名方式
      https://api.example.com            尽量将API部署在专用域名(会存在跨域问题)	
      https://www.example.com	
    2)url方式	
      https://example.org	
      https://example.org/api/                        API很简单
 	3、版本
      URL,如:https://api.example.com/v1/
      请求头       跨域时,引发发送多次请求
	4、面向资源编程: 路径,视网络上任何东西都是资源,均使用名词表示(可复数)
      https://api.example.com/v1/zoos
      https://api.example.com/v1/animals
      https://api.example.com/v1/employees
 	5、method
      GET      :从服务器取出资源(一项或多项)
      POST    :在服务器新建一个资源
      PUT      :在服务器更新资源(客户端提供改变后的完整资源)
      PATCH  :在服务器更新资源(客户端提供改变的属性)
      DELETE :从服务器删除资源
 	 6、过滤,通过在url上传参的形式传递搜索条件
 	 	https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
	  https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
	  https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
	  https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
	  https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
	 7、状态码
'''1. 2XX请求成功'''
# 200 请求成功,一般用于GET与POST请求
# 201 Created - [POST/PUT/PATCH]:用户新建或修改数据成功。
# 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
# 204 NO CONTENT - [DELETE]:用户删除数据成功。
'''2. 3XX重定向'''
# 301 NO CONTENT - 永久重定向
# 302 NO CONTENT - 临时重定向
'''3. 4XX客户端错误'''
# 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误。
# 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
# 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
# 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录。
# 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
# 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
# 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
'''4. 5XX服务端错误'''
# 500 INTERNAL SERVER ERROR - [*]:服务器内部错误,无法完成请求
# 501 Not Implemented     服务器不支持请求的功能,无法完成请求更多状态码参考:https://www.runoob.com/http/http-status-codes.html

django实现restful

# urls.py
urlpatterns = [
    url(r'^users', Users.as_view()),
]
# views.py
from django.views import View
from django.http import JsonResponse
 
class Users(View):
    def get(self, request, *args, **kwargs):
        result = {
            'status': True,
            'data': 'response data'
        }
        return JsonResponse(result, status=200)
 
    def post(self, request, *args, **kwargs):
        result = {
            'status': True,
            'data': 'response data'
        }
        return JsonResponse(result, status=200) 

基于drf框架实现

1.serializer-APIView

# models.py
class Classroom(models.Model):
    """
    班级表
    """
    class_name = models.CharField(max_length=32, verbose_name="班级名称", unique=True)
    address = models.CharField(max_length=32, null=True)

    class Meta:
        db_table = "pp_class"

    def __str__(self):
        return self.class_name
        
# serializer.py
class ClassroomSerializer(serializers.Serializer):
    class_name = serializers.CharField(max_length=32, required=True, label='班级名')
    address = serializers.CharField(max_length=32, label='地址')

    def create(self, validated_data):
        return Classroom.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.class_name = validated_data.get('class_name', instance.class_name)
        instance.address = validated_data.get('address', instance.address)
        instance.save()
        return instance
        
# views.py
class ClassroomView(APIView):
    def get(self, request):
    	# 查询
        class_obj = Classroom.objects.all().order_by('-id')
        ser_obj = ClassroomSerializer(class_obj , many=True)
        return Response(ser_obj.data)

    def post(self, request):
    	# 添加
        data = request.data
        ser_obj = ClassroomSerializer(data=data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        else:
            return Response(ser_obj.errors)

    def put(self, request):
    	# 修改
        data = request.data
        instance = Classroom.objects.filter(class_name=data['class_name']).first()  # 查询要修改的对象
        ser_obj = ClassroomSerializer(instance=instance, data=data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        else:
            return Response(ser_obj.errors)

添加时数据自定义验证

方法一:在views中验证

# serializer.py
class ClassroomSerializer(serializers.Serializer):
    class_name = serializers.CharField(max_length=32, required=True, label='班级名')
    address = serializers.CharField(max_length=32, label='地址')

    def create(self, validated_data):
        return Classroom.objects.create(**validated_data)
# views.py
class ClassroomView(APIView):

    def post(self, request):
        data = request.data
        # 验证地址 是不是 beijing
        if data['address'] != 'beijing':
            return Response({'msg': '信息不在北京'})

        ser_obj = ClassroomSerializer(data=data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        else:
            return Response(ser_obj.errors)

方法二:序列化中验证

# serializer.py
class ClassroomSerializer(serializers.Serializer):
    class_name = serializers.CharField(max_length=32, required=True, label='班级名')
    address = serializers.CharField(max_length=32, label='地址')

    def create(self, validated_data):
        return Classroom.objects.create(**validated_data)
	# 自定义验证规则
    def validate(self, attrs):
        if attrs.get('address') != 'beijing':
            raise serializers.ValidationError('信息不在北京')
        return attrs
# views.py
class ClassroomView(APIView):

    def post(self, request):
        data = request.data
        ser_obj = ClassroomSerializer(data=data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        else:
            return Response(ser_obj.errors)

多对多一对多序列化嵌套

# models.py
from django.db import models


class Role(models.Model):
    """
    角色表
    """
    role_name = models.CharField(max_length=32, unique=True)

    class Meta:
        db_table = "pp_role"


class Classroom(models.Model):
    """
    班级表
    """
    class_name = models.CharField(max_length=32, verbose_name="班级名称", unique=True)
    address = models.CharField(max_length=32, null=True)

    class Meta:
        db_table = "pp_class"

    def __str__(self):
        return self.class_name


class User(models.Model):
    """
    用户表
    """
    username = models.CharField(max_length=32, verbose_name="姓名")
    age = models.IntegerField(verbose_name="年龄")
    home = models.CharField(verbose_name="家乡", null=True, max_length=32)
    hight = models.IntegerField(verbose_name="身高", null=True)

    # 多对多
    roles = models.ManyToManyField(Role)

    # 一对多
    classrooms = models.ForeignKey(Classroom, on_delete=models.CASCADE, null=True)

    class Meta:
        db_table = "pp_user"

# serializer.py
from rest_framework import serializers
from .models import *

class ClassroomSerializer(serializers.Serializer):
    class_name = serializers.CharField(max_length=32, required=True, label='班级名')
    address = serializers.CharField(max_length=32, label='地址')

class RoleSerializer(serializers.Serializer):
    role_name = serializers.CharField(max_length=32, required=True, label='角色名')

class UserSerializer(serializers.Serializer):
    username = serializers.CharField(max_length=32)
    age = serializers.IntegerField()
    home = serializers.CharField(max_length=32, allow_null=True)
    hight = serializers.IntegerField(allow_null=True)

    # 多对多
    roles = RoleSerializer(many=True)

    # 一对多
    classrooms = ClassroomSerializer()
 
# views.py
# 查询用户
class UserView(APIView):
    def get(self, request):
        # 查询
        user_obj = User.objects.all()
        ser_obj = UserSerializer(user_obj, many=True)
        return Response(ser_obj.data)

查询结果:

[
    {
        "username": "张三",
        "age": 22,
        "home": "北京",
        "hight": 180,
        "roles": [
            {
                "role_name": "教师"
            },
            {
                "role_name": "警察"
            }
        ],
        "classrooms": {
            "class_name": "2002A",
            "address": "北京"
        }
    },
    {
        "username": "李四",
        "age": 33,
        "home": "啊啊",
        "hight": 180,
        "roles": [
            {
                "role_name": "教师"
            }
        ],
        "classrooms": {
            "class_name": "2002B",
            "address": "beijing"
        }
    },
    {
        "username": "王五",
        "age": 22,
        "home": "北京",
        "hight": 180,
        "roles": [],
        "classrooms": {
            "class_name": "2002c",
            "address": "beij"
        }
    }
]

用户访问次数/频率限制

全局使用

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/day',
        'user': '1000/day'
    }
}

分页

views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination

from .serializer import *


class PageNum(PageNumberPagination):
    # 指定查询字符串中代表每页返回数据数量的参数名,默认None
    page_size_query_param = "max_page"
    # 指定查询字符串中代表页码的参数名,不指定默认值page
    # page_query_param = 'page'
    # max_page_size =  10   # 一页最多的结果条数,


class ClassroomView(APIView):
    def get(self, request):
        class_obj = Classroom.objects.all().order_by('-id')
        # 分页
        paginator = PageNum()
        result_page = paginator.paginate_queryset(class_obj, request)
        ser_obj = ClassroomSerializer(result_page, many=True)
        return Response(ser_obj.data)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值