python django restful框架_Django Rest Framework框架

Django Rest Framework框架介绍

API接口简称API,它与网站路由的实现原理相同。当用户使用GET或者POST方式访问API时,API以JSON或字符串的数据内容返回给用户,网站的路由返回的是HTML网页信息,这与API返回的数据格式有所不同

1.1  DRF的安装与配置

开发网站的API可以在视图函数中使用响应类JsonResponse实现,它将字典格式的数据作为响应内容。使用响应类JsonResponse开发API需要根据用户请求信息构建字典格式的数据内容,数据构建的过程可能涉及模型的数据查询、数据分页处理等业务逻辑,这种方式开发API很容易造成代码冗余,不利于功能的变更和维护。

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

在使用Django Rest Framework框架之前,首先安装Django Rest Framework框架,建议使用pip完成安装,安装指令如下:

pip install djangorestframework

框架安装成功后,通过简单的例子来讲述如何在Django中配置Django Rest Framework的功能。以MyDjango为例,在项目应用index中创建serializers.py文件,该文件用于定义Django Rest Framework的序列化类;然后在MyDjango的settings.py中设置功能配置,功能配置如下:

#事先创建一个django项目和index的app应用,再settings.py里面添加如下:

INSTALLED_APPS =['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','index.apps.IndexConfig',

#添加Django Rest Framework框架'rest_framework']

#Django Rest Framework框架设置信息

#分页设置

REST_FRAMEWORK = {'DEFAULT_PAGINATION_CLASS':

'rest_framework.pagination.PageNumberPagination',

#每页显示多少条数据

'PAGE_SIZE': 2

}

上述配置信息用于实现Django Rest Framework的功能配置,配置说明如下:

(1)在INSTALLED_APPS中添加API框架的功能配置,这样能使Django在运行过程中自动加载Django Rest Framework的功能。

(2)配置属性REST_FRAMEWORK以字典的形式表示,用于设置Django Rest Framework的分页功能。

完成settings.py的配置后,下一步定义项目的数据模型。在index的models.py中分别定义模型PersonInfo和Vocation,代码如下:

#index的models.py

from django.db importmodels#Create your models here.

classPersonInfo(models.Model):

id= models.AutoField(primary_key=True)

name= models.CharField(max_length=20)

age=models.IntegerField()

hireDate=models.DateField()def __str__(self):returnself.nameclassMeta:

verbose_name= '人员信息'verbose_name_plural=verbose_nameclassVocation(models.Model):

id= models.AutoField(primary_key=True)

job= models.CharField(max_length=20)

title= models.CharField(max_length=20)

payment= models.IntegerField(null=True,blank=True)

name= models.ForeignKey(PersonInfo, on_delete=models.Case)def __str__(self):returnstr(self.id)classMeta:

verbose_name= '职业信息'verbose_name_plural= verbose_name

index/models.py

将定义好的模型执行数据迁移,在项目的db.sqlite3数据库文件中生成数据表,并对数据表index_personinfo和index_vocation添加数据内容,如下图所示:

数据表index_personinfo和index_vocation

1.2  序列化类Serializer

项目环境搭建完成后,我们将使用Django Rest Framework快速开发API。首先在项目应用index的serializers.py中定义序列化类MySerializer,代码如下:

#index的serializers.py

from rest_framework importserializersfrom .models importPersonInfo, Vocation#定义Serializer类#设置模型Vocation的字段name的下拉内容

nameList = PersonInfo.objects.values('name').all()

NAME_CHOICES= [item['name'] for item innameList]classMySerializer(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.ChoiceField(choices=NAME_CHOICES,default=1)

#模型Vocation的字段name是外键字段,它指向模型PersonInfo

#因此,外键字段可以使用PrimaryKeyRelatedField

name = serializers.PrimaryKeyRelatedField(queryset=nameList)#重写create函数,将API数据保存到数据表index_vocation中

defcreate(self, validated_data):return Vocation.objects.create(**validated_data)#重写update函数,将API数据更新到数据表index_vocation中

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

index/serializers.py

自定义序列化类MySerializer继承父类Serializer,父类Serializer是由Django Rest Framework定义的,它的定义过程与表单类Form十分相似。在PyCharm里打开父类Serializer的源码文件,分析序列化类Serializer的定义过程。

Serializer继承父类BaseSerializer,装饰器add_metaclass设置元类SerializerMetaclass。我们以流程图的形式说明Serializer的继承关系,如下图:

Serializer的继承关系

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

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

read_only:设置序列化字段的只读属性

write_only:设置序列化字段的编辑属性

required:设置序列化字段的数据是否为空,默认值为True

default:设置序列化字段的默认值

initial:设置序列化字段的初始值

source:为序列化字段指定一个模型字段来源,如(email='user.email')

label:用于生成label标签的网页内容

help_text:设置序列化字段的帮助提示信息

style:以字典格式化表示,控制模板引擎如何渲染序列化字段

error_messages:设置序列化字段的错误信息,以字段格式表示,包含null、blank、invalid、invalid_choice、unique等键值

validators:与表单类的validators相同,这是自定义数据验证规则,以列表格式表示,列表元素为数据验证的函数名

allow_null:设置序列化字段是否为None,若为True,则序列化字段的值允许为None

自定义序列化类MySerializer还定义了关系字段name,重写了父类BaseSerializer的create和update函数。关系字段可以在源码文件relations.py中找到定义过程,每个关系字段都有代码注释说明,本节不再重复讲述。

下一步使用序列化类MySerializer实现API开发,在index的urls.py中分别定义路由myDef和路由myClass,路由信息的代码如下:

#index的urls.py

from django.urls importpathfrom .views import *urlpatterns=[#视图函数

path('', vocationDef, name='myDef'),#视图类

path('myClass/', vocationClass.as_view(), name='myClass'),

]

路由myDef对应视图函数vocationDef,它以视图函数的方式使用MySerializer实现模型Vocation的API接口;路由myClass对应视图。类vocationClass,它以视图类的方式使用MySerializer实现模型Vocation的API接口。因此,视图函数vocationDef和视图类vocationClass的定义过程如下:

#index的views.py

from django.shortcuts importrenderfrom .models importPersonInfo, Vocationfrom .serializers importMySerializerfrom rest_framework.views importAPIViewfrom rest_framework.response importResponsefrom rest_framework importstatusfrom rest_framework.pagination importPageNumberPaginationfrom rest_framework.decorators importapi_view#Create your views here.

@api_view(['GET', 'POST'])defvocationDef(request):if request.method == 'GET':

q=Vocation.objects.all()#分页查询,需要在settings.py中设置REST_FRAMEWORK属性

pg =PageNumberPagination()

p=pg.paginate_queryset(queryset=q, request=request)#将分页后的数据传递给MySerializer,生成JSON数据对象

serializer = MySerializer(instance=p, many=True)#返回对象Response由Django Rest Framework实现

returnResponse(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))ifinstance:#修改数据

MySerializer().update(instance, data)else:#创建数据

MySerializer().create(data)return Response('Done', status=status.HTTP_201_CREATED)classvocationClass(APIView):#GET请求

defget(self, request):

q=Vocation.objects.all()#分页查询,需要在settings.py中设置REST_FRAMEWORK属性

pg =PageNumberPagination()

p= pg.paginate_queryset(queryset=q, request=request, view=self)#将分页后的数据传递给MySerializer,生成JSON数据对象

serializer = MySerializer(instance=p, many=True)#返回对象Response由Django Rest Framework实现

returnResponse(serializer.data)#POST请求

defpost(self, request):

data=request.data

id= data['name']

data['name'] = PersonInfo.objects.filter(id=id).first()

instance= Vocation.objects.filter(id=data.get('id', 0))ifinstance:#修改数据

MySerializer().update(instance, data)else:#创建数据

MySerializer().create(data)return Response('Done', status.HTTP_201_CREATED)

index/views.py

视图函数vocationDef和视图类vocationClass实现的功能是一致的,若使用视图函数开发API接口,则必须对视图函数使用装饰器api_view;若使用视图类,则必须继承父类APIView,这是Django Rest Framework明确规定的。上述的视图函数vocationDef和视图类vocationClass对GET请求和POST请求进行不同的处理。

当用户在浏览器上访问路由myDef或路由myClass的时候,视图函数vocationDef或视图类vocationClass将接收GET请求,该请求的处理过程说明如下:

(1)视图函数vocationDef或视图类vocationClass查询模型Vocation所有数据,并将数据进行分页处理。

(2)分页功能有Django Rest Framework的PageNumberPagination实现,他是在Django内置分页功能的基础上进行封装的,分页属性设置在settings.py的REST_FRAMEWORK中。

(3)分页后的数据传递给序列化类MySerializer,转化成JSON数据,最后由Django Rest Framework框架的Response完成用户响应。

运行MyDjango项目,分别访问路由myDef和路由myClass,发现两者返回的网页内容是一致的。如果在路由地址中设置请求参数page,就可以获取某分页的数据信息,如下图:

用户向路由myDef或路由myClass发送POST请求时,视图函数vocationDef或视图类vocationClass的处理过程说明如下:

(1)视图函数vocationDef或视图类vocationClass获取请求参数,将请求参数id作为模型字段id的查询条件,在模型Vocation中进行数据查询

(2)如果存在查询对象,就说明模型Vocation已存在相应的数据信息,当前POST请求将视为修改模型Vocation的已有数据。

(3)如果不存在查询对象,就把当前请求的数据信息添加在模型Vocation中

在下图的网页正下方找到Content文本框,以模型Vocation的字段编写单个JSON数据,单击"POST"按钮即可实现数据的新增或修改

1.3  模型序列化类ModelSerializer

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

以1.2小节的MyDjango为例,将自定义的MySerializer改为VocationSerializer,序列化类VocationSerializer继承父类ModelSerializer,它能与模型Vocation完美结合,无须开发者定义序列化字段。在index的serializers.py中定义VocationSerializer,代码如下:

classVocationSerializer(serializers.ModelSerializer):classMeta:

model=Vocation

fields= '__all__'

#fields=('id','job','title','payment','name')

分析VocationSerializer得知,属性model将模型Vocation与ModelSerializer进行绑定;属性fields用于设置哪些模型字段转化为序列化字段,属性值__all__代表模型所有字段转化为序列化字段,如果只设置部分模型字段,属性fields的值就可以使用元组或列表表示,元组或列表的每个元素代表一个模型字段。

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

from django.shortcuts importrenderfrom .models importPersonInfo, Vocationfrom .serializers importVocationSerializerfrom rest_framework.views importAPIViewfrom rest_framework.response importResponsefrom rest_framework importstatusfrom rest_framework.pagination importPageNumberPaginationfrom rest_framework.decorators importapi_view

@api_view(['GET', 'POST'])defvocationDef(request):if request.method == 'GET':

q= Vocation.objects.all().order_by('id')#分页查询,需要在settings.py中设置REST_FRAMEWORK属性

pg =PageNumberPagination()

p=pg.paginate_queryset(queryset=q, request=request)#将分页后的数据传递给MySerializer,生成JSON数据对象

serializer = VocationSerializer(instance=p, many=True)#返回对象Response由Django Rest Framework实现

returnResponse(serializer.data)elif request.method == 'POST':#获取请求数据

id = request.data.get('id', 0)#判断请求参数id在模型Vocation中是否存在

#若存在,则执行数据修改;否则新增数据

operation = Vocation.objects.filter(id=id).first()#数据验证

serializer = VocationSerializer(data=request.data)ifserializer.is_valid():ifoperation:

data=request.data

id= data['name']

data['name'] = PersonInfo.objects.filter(id=id).first()

serializer.update(operation, data)else:#保存到数据库

serializer.save()#返回对象Response由Django Rest Framework实现

returnResponse(serializer.data)return Response(serializer.errors, status=404)classvocationClass(APIView):#GET请求

defget(self, request):

q= Vocation.objects.all().order_by('id')#分页查询,需要在settings.py中设置REST_FRAMEWORK属性

pg =PageNumberPagination()

p= pg.paginate_queryset(queryset=q, request=request, view=self)

serializer= VocationSerializer(instance=p, many=True)#返回对象Response由Django Rest Framework实现

returnResponse(serializer.data)#POST请求

defpost(self, request):#获取请求数据

id = request.data.get('id', 0)

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

serializer= VocationSerializer(data=request.data)#数据验证

ifserializer.is_valid():ifoperation:

data=request.data

id= data['name']

data['name'] = PersonInfo.objects.filter(id=id).first()

serializer.update(operation, data)else:#保存到数据库

serializer.save()#返回对象Response由Django Rest Framework实现

returnResponse(serializer.data)return Response(serializer.errors, status=404)

index/views.py

视图函数vocationDef和视图类vocationClass的业务逻辑与1.2小节的业务逻辑是相同的,而对于POST请求的处理过程,本节与1.2小节实现的功能是一致,但使用的函数方法有所不同。

1.4  序列化的嵌套使用

在开发过程中,我们需要对多个JSON数据进行嵌套使用,比如将模型PersonInfo和Vocation的数据组合存放在同一个JSON数据中,两个模型的数据通过外键字段name进行关联。

模型之间必须存在数据关系才能实现数据嵌套,数据关系可以是一对一、一对多或多对多的,不同的数据关系对数据嵌套的读写财政会有细微的差异。以1.3小结的MyDJnaog为例,在index的serializers.py中定义PersonInfoSerializer和VocationSerializer,分别对应模型PersonInfo和Vocation,模型序列化类的定义如下:

from rest_framework importserializersfrom .models importPersonInfo, Vocation#定义ModelSerializer类

classPersonInfoSerializer(serializers.ModelSerializer):classMeta:

model=PersonInfo

fields= '__all__'

#定义ModeolSerializer类

classVocationSerializer(serializers.ModelSerializer):

name=PersonInfoSerializer()classMeta:

model=Vocation

fields= ('id', 'job', 'title', 'payment', 'name')defcreate(self, validated_data):#从validated_data中获取模型PersonInfo的数据

name = validated_data.get('name', '')

id= name.get('id', 0)

p= PersonInfo.objects.filter(id=id).first()#根据id判断模型PersonInfo是否存在数据对象

#若存在数据对象,则只对Vocation新增数据

#若不存在,则先对模型PersonInfo新增数据

#再对模型Vocation新增数据

if notp:

p= PersonInfo.objects.create(**name)

data=validated_data

data['name'] =p

v= Vocation.objects.create(**data)returnvdefupdate(self, instance, validated_data):#从validated_data中获取模型PersonInfo的数据

name = validated_data.get('name', '')

id= name.get('id', 0)

p= PersonInfo.objects.filter(id=id).first()#判断外键name是否存在模型PersonInfo

ifp:#若存在,则先更新模型PersonInfo的数据

PersonInfo.objects.filter(id=id).update(**name)#再更新模型Vocation的数据

data =validated_data

data['name'] =p

id= validated_data.get('id', '')

v= Vocation.objects.filter(id=id).update(**data)return v

index/serializers.py

从上述代码看到,序列化类VocationSerializer对PersonInfoSerializer进行实例化并复制给变量name,而属性fields的name代表模型Vocation的外键字段name,同时也是变量name。换句话说,序列化字段name代表模型Vocation的外键字段name,而变量name作为序列化字段name的数据内容。

变量name的名称必须与模型外键字段名称或者序列化字段名称一致,否则模型外键字段或者序列化字段无法匹配变量name,从而提示异常信息。

序列化类VocationSerializer还重写了数据的新增函数create和修改函数update,因为不同数据关系的数据读写方式不相同,并且不同的开发需求可能导致数据读写方式有所不同。新增函数create和修改函数update的业务逻辑较为相似,业务逻辑说明如下:

(1)从用户的请求参数(函数参数validated_data)获取模型PersonInfo的主键id,根据主键id查询模型PersonInfo是否已存在数据对象。

(2)如果存在模型PersonInfo的数据对象,那么update函数首先修改模型PersonInfo的数据,然后修改模型Vocation的数据。

(3)如果不存在模型PersonInfo的数据对象,那么create函数在模型PersonInfo的数据然后在模型Vocation中新增数据,确保模型Vocation的外键字段name不为空,使两个模型之间构成一对多的数据关系。

下一步对视图函数vocationFef和视图类vocationClass的代码进行调整,代码的业务逻辑与1.3小结的相同,代码调整如下:

from django.shortcuts importrenderfrom .models importPersonInfo, Vocationfrom .serializers importVocationSerializerfrom rest_framework.views importAPIViewfrom rest_framework.response importResponsefrom rest_framework importstatusfrom rest_framework.pagination importPageNumberPaginationfrom rest_framework.decorators importapi_view

@api_view(['GET', 'POST'])defvocationDef(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)#返回对象Response由Django Rest Framework实现

returnResponse(serializer.data)elif request.method == 'POST':#获取请求数据

id = request.data.get('id', 0)#判断请求参数id在模型Vocation中是否存在

#若存在,则执行数据修改;否则新增数据

operation = Vocation.objects.filter(id=id).first()#数据验证

serializer = VocationSerializer(data=request.data)ifserializer.is_valid():ifoperation:

serializer.update(operation, request.data)else:#保存到数据库

serializer.save()#返回对象Response由Django Rest Framework实现

returnResponse(serializer.data)return Response(serializer.errors, status=404)classvocationClass(APIView):defget(self, request):

q= Vocation.objects.all().order_by('id')#分页查询,需要在settings.py中设置REST_FRAMEWORK属性

pg =PageNumberPagination()

p= pg.paginate_queryset(queryset=q, request=request, view=self)

serializer= VocationSerializer(instance=p, many=True)#返回对象Response由Django Rest Framework实现

returnResponse(serializer.data)#POST请求

defpost(self, request):#获取请求数据

id = request.data.get('id', 0)

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

serializer= VocationSerializer(data=request.data)#数据验证

ifserializer.is_valid():ifoperation:

serializer.update(operation, request.data)else:#保存到数据库

serializer.save()#返回对象Response由Django Rest Framework实现

returnResponse(serializer.data)return Response(serializer.errors, status=404)

index/views.py

最后运行MyDjango,在浏览器上访问127.0.0.1:8000,模型Vocation的每行数据嵌套了模型PersonInfo的某行数据,两个模型的数据嵌套主要由模型Vocation的外键字段name实现关联

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值