Django - Rest Framework 框架

DRF 的安装与配置

为了简化API的开发过程,我们可以使用Django Rest Framework 框架实现API开发。使用框架开发不仅能减少代码冗余,还可以规范代码的编写格式,这对企业级开发来说很有必要,毕竟每个开发人员的编程风格存在一定的差异,开发规范可以方便其他开发人员查看和修改。

在使用Django Rest Framework 之前,首先安装 Django Rest Framework

pip install djangorestframework

安装完成之后进行配置:

# MyDjango\setting.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'index',
    'user',
    'rest_framework' # 添加 Django Rest Framework 框架
]

# Django Rest Framework 框架 设置信息
# 分页设置
REST_FRAMEWORK = {'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
                  # 每页显示多少数据
                  'PAGE_SIZE': 2}

案例以下面表讲解:

数据:

序列化类 Serializer

在项目的应用index 的 serializers.py 中定义序列化类:

class VocationSerializer(serializers.Serializer):
    id =  serializers.IntegerField(read_only=True)
    job = serializers.CharField(max_length=100)
    title = serializers.CharField(max_length=100)
    payment= serializers.CharField(max_length=100)

    name = serializers.PrimaryKeyRelatedField(queryset=NAME_LIST)


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

    def update(self, instance, validated_data):
        return instance.update(**validated_data)

自定义序列化类 VocationSerializer 的字段对应 模型Vocation 的字段,序列化字段的数据类型可以在 Rest Framework 的源码文件fields.py 中找到定义过程,它们都继承父类Field。

在定义序列化字段的时候,每个序列化字段允许设置参数信息,分析父类Field 的初始化参数,它们适用于所有序列化字段的参数设置,说明如下:

  • read_only: 设置序列化字段的只读属性
  • write_only:设置序列化字段的编辑属性
  • required: 设置序列化字段的数据是否为空,默认值为True
  • default: 设置序列化字段的默认值
  • initial:设置序列化字段的初始值
  • source:为序列化字段指定一个模型字段来源,如(email='user.email')
  • allow_null:设置序列化字段是否为None ,若为True ,则序列化字段的值允许为None

自定义序列化类VocationSerializer 还定义了关系字段 name,重写了父类 BaseSerializer 的 create 和 update 函数。关系字段可以在源码文件relations.py 中找到定义过程。

定义路由:

# index\urls.py

urlpatterns = [
    # path('<pk>/<age>.html', index.as_view(), name='index')
    path('', vocationDef , name='myDef'),
    path('vocationClass/', VocationClass.as_view(), name='vocationClass')
]
# index\views.py
from .models import Vocation
from .serializers import VocationSerializer
from rest_framework import status
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.views import APIView


@api_view(['GET', 'POST'])
def vocationDef(request):
    if request.method == 'GET':
        q = Vocation.objects.all().order_by('id')
        pg = PageNumberPagination()
        p = pg.paginate_queryset(queryset=q, request=request)
        # 序列化
        serializer = VocationSerializer(instance=p, many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
        data = request.data
        id = data['name']
        data['name'] = PersonInfo.objects.filter(id=id).first()
        instance = Vocation.objects.filter(id=data.get('id', 0))

        if instance:
            # 修改数据
            VocationSerializer().update(instance, data)
        else:
            # 创建数据
            VocationSerializer().create(data)
        return Response('Done', status=status.HTTP_201_CREATED)


class VocationClass(APIView):

    def get(self, request):
        q = Vocation.objects.all().order_by('id')
        pg = PageNumberPagination()
        p = pg.paginate_queryset(queryset=q, request=request)
        # 将分页后的数据传递给 VocationSerializer,生成JSON数据对象
        serializer = VocationSerializer(instance=p, many=True)
        # 返回对象 有 Rest Framework 框架实现
        return Response(serializer.data)

    def post(self, request):
        """修改或新增"""
        request_body = request.data
        print(request_body)  # {'id': 1, 'job': '软件工程师1', 'title': 'Python开发', 'payment': '10000', 'name': 2}

        personinfo_id = request_body['name']

        request_body['name'] = PersonInfo.objects.filter(id=personinfo_id).first()  # first 返回的是一个obj
        print(request_body)  # {'id': 1, 'job': '软件工程师2', 'title': 'Python开发', 'payment': '10000', 'name': <PersonInfo: Tim>}

        instance = Vocation.objects.filter(id=request_body.get('id', 0))

        if instance:
            # 修改数据
            VocationSerializer().update(instance, request_body)
        else:
            # 创建数据
            VocationSerializer().create(request_body)
        return Response('Done', status=status.HTTP_201_CREATED)

vocationDef 视图函数验证:

访问: http://localhost:8000/

查询到前2条数据

新增一条数据:

结果:

模型序列化类 ModelSerializer

序列化类 Serializer 可以与模型结合使用, 从而实现模型的数据读写操作。但是序列化类 Serializer 定义的字段必须与模型字段互相契合,否则在使用过程中很容易提示异常信息。为了简化序列化类的定义过程,Django Rest Framework 定义序列化类 ModelSerializer 。

使用案例:

# index\serializers.py
from rest_framework import serializers
from .models import Vocation


class VocationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Vocation
        fields = '__all__'
        # fields = {'id', 'job', 'title', 'payment', 'name'}

属性model 将 模型Vocation 与 ModelSerializer 进行绑定,属性fields 用于设置哪些模型字段转化为 序列化字段,属性值'all' 代表模型所有字段转化为序列化字段,如果只设置部分模型字段,属性fields 的值就可以使用元组或列表。

下一步重新定义视图函数 和视图类, 使用模型序列化类 VocationSerializer 实现模型 Vocation 的 API 接口

# index\views.py
@api_view(['GET', 'POST'])
def vocationDef(request):
    if request.method == 'GET':
        q = Vocation.objects.all().order_by('id')
        pg = PageNumberPagination()
        p = pg.paginate_queryset(queryset=q, request=request)
        # 序列化
        serializer = VocationSerializer(instance=p, many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
        vocation_id = request.data.get('id', 0)

        operation = Vocation.objects.filter(id=vocation_id).first()
        serializer = VocationSerializer(data=request.data)

        if serializer.is_valid():
            if operation:
                # 修改数据
                data = request.data
                id = data['name']
                data['name'] = PersonInfo.objects.filter(id=id).first()
                serializer.update(operation, data)
            else:
                # save
                serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=404)


class VocationClass(APIView):

    def get(self, request):
        q = Vocation.objects.all().order_by('id')
        pg = PageNumberPagination()
        p = pg.paginate_queryset(queryset=q, request=request)
        # 将分页后的数据传递给 VocationSerializer,生成JSON数据对象
        serializer = VocationSerializer(instance=p, many=True)
        # 返回对象 有 Rest Framework 框架实现
        return Response(serializer.data)

    def post(self, request):
        """修改或新增"""
        vocation_id = request.data.get('id', 0)

        operation = Vocation.objects.filter(id=vocation_id).first()

        serializer = VocationSerializer(data=request.data)
        if serializer.is_valid():
            if operation:
                # 修改数据
                data = request.data
                id = data['name']
                data['name'] = PersonInfo.objects.filter(id=id).first()  # vocation的 外键name,关联上person obj
                serializer.update(operation, data)  # operation: 更新行, data:按data数据进更新
            else:
                # 新增数据
                serializer.save()
        return Response(serializer.errors, status=404)

序列化的嵌套使用

# index\serializers.py
class PersonInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = PersonInfo
        fields = '__all__'


class VocationSerializer(serializers.ModelSerializer):
    name = PersonInfoSerializer()

    class Meta:
        model = Vocation
        fields = {'id', 'job', 'title', 'payment', 'name'}

    def create(self, validated_data):
        name = validated_data['name']
        person_info_id = name.get('id', 0)
        p = PersonInfo.objects.filter(id=person_info_id).first()
        if not p:
            # 新建personinfo
            p = PersonInfo.objects.create(**name)
        validated_data['name'] = p
        v = Vocation.objects.create(**validated_data)
        return v

    def update(self, instance, validated_data):
        personinfo_data = validated_data['name']
        person_info_id = personinfo_data.get('id', 0)
        p = PersonInfo.objects.filter(id=person_info_id).first()

        if p:
            # 如果存在personinfo 更新personinfo
            p = PersonInfo.objects.filter(id=person_info_id).update(**personinfo_data)
            # 再更新 vocation
            validated_data['name'] = p
            v = Vocation.objects.filter(validated_data['id']).update(**validated_data)
            return v
# index\views.py
@api_view(['GET', 'POST'])
def vocationDef(request):
    if request.method == 'GET':
        q = Vocation.objects.all().order_by('id')
        pg = PageNumberPagination()
        p = pg.paginate_queryset(queryset=q, request=request)
        # 序列化
        serializer = VocationSerializer(instance=p, many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
        vocation_id = request.data.get('id', 0)

        operation = Vocation.objects.filter(id=vocation_id).first()
        serializer = VocationSerializer(data=request.data)

        if serializer.is_valid():
            if operation:
                serializer.update(operation, request.data)
            else:
                # save
                serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=404)


class VocationClass(APIView):

    def get(self, request):
        q = Vocation.objects.all().order_by('id')
        pg = PageNumberPagination()
        p = pg.paginate_queryset(queryset=q, request=request)
        # 将分页后的数据传递给 VocationSerializer,生成JSON数据对象
        serializer = VocationSerializer(instance=p, many=True)
        # 返回对象 有 Rest Framework 框架实现
        return Response(serializer.data)

    def post(self, request):
        """修改或新增"""
        vocation_id = request.data.get('id', 0)
        operation = Vocation.objects.filter(id=vocation_id).first()
        serializer = VocationSerializer(data=request.data)
        if serializer.is_valid():
            if operation:
                serializer.update(operation, request.data)  
            else:
                # 新增数据
                serializer.save()
        return Response(serializer.errors, status=404)
posted @ 2024-05-12 20:26  chuangzhou  阅读(3)  评论(0编辑  收藏  举报