Day 22 drf related use
1. Installation
note:After installing drf, our django will be automatically upgraded to the latest version. Students with lower versions need to change it back. Another point is that drf and django versions are compatible, so we need to find a suitable drf for our django
registered
After downloading, we need to register under the app in the setting
Two, restful specification
REST has nothing to do with technology, it represents an architectural style (resource-oriented architecture), REST is the abbreviation of Representational State Transfer, Chinese translated as "representational state transfer"
- Representational State Transfer: Representational State Transfer
- The design style of the Web API interface is especially suitable for the application mode where the front and back ends are separated
- Regardless of language and platform, any framework can write an api interface that conforms to restful specifications
Ten rules
-
**Data security: **URL links generally use https protocol for transmission
-
Interface feature performance: api keyword identification (you can see at a glance this isapi interface)
-Https: //api.baidu.com/books/
-https: //www.baidu.com/api/books/ -
Multi-version coexistence: the interface version is identified in the url link (just like XuMulti-versionSoftware can still be used they just usedDifferent interfaces)
-https://api.baidu.com/v1/books/
-https://api.baidu.com/v2/books/ -
Data is a resource, using nouns (plural) ***********
-Interfaces are generally used to complete the interaction of front and back data, interactive data we call resources
-generally recommendedPlural form of resource, Do not use verbs
-query all books-
https
://api.baidu.com/books/-https://api.baidu.com/get_all_books/ # error demonstration-
https://api.baidu.com/delete- user # Demonstration of error-
https://api.baidu.com/user # Example of deleting a user: Question: Is it to delete or check? -
Resource operation is determined by the request method:
https://api.baidu.com/books - get请求:获取所有书
https://api.baidu.com/books/1 - get请求:获取主键为1的书
https://api.baidu.com/books - post请求:新增一本书书
https://api.baidu.com/books/1 - put请求:整体修改主键为1的书
https://api.baidu.com/books/1 - patch请求:局部修改主键为1的书
https://api.baidu.com/books/1 - delete请求:删除主键为1的书
-
Filter, pass search conditions by uploading parameters in URL
https://api.example.com/v1/zoos?limit=10 :指定返回记录的数量 https://api.example.com/v1/zoos?offset=10&limit=3:指定返回记录的开始位置 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:指定筛选条件
-
Error message in the returned result
-{'code':100,'msg':'Failed because of xx') -
The returned result should meet the following specifications
GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象(字典) POST /collection:返回新生成的资源对象 (新增后的对象字典) PUT /collection/resource:返回完整的资源对象 (修改后的对象字典) PATCH /collection/resource:返回完整的资源对象 (修改后的对象字典) DELETE /collection/resource:返回一个空文档 ()
-
Link address in the returned data
-查询id为1的图书接口,返回结果示例
{'code':100,
'msg':'成功',
'result':
{'title':'superstar',
'price':12.3,
'publish':'https://127.0.0.1/api/v1/publish/3'
}
}
Three, APIview source code analysis
1. APIview的as_view
The closure function view of Vew is still executed internally
Disabled csrf
Everything is an object, and functions are also objects,函数地址.name = ssd
2. The closure function view in as_view in the native View class
Essentially executed self.dispatch(request, *args, **kwargs)
, the dispatch of APIView is executed
3. APIView's dispatch
def dispatch(self, request, *args, **kwargs):
# DRF的Request类的对象,内部有request._request,是原生request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
try:
self.initial(request, *args, **kwargs)
'''
#认证,权限,频率
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
'''
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
# 全局的异常捕获
response = self.handle_exception(exc)
# 把视图函数(类)返回的response,又包装了一下
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
Four, request analysis
1 Request类
-request._request:原生request
-request.data : post请求提交的数据(urlencoded,json,formdata)
-request.user :不是原生的user了
-request.query_params :原生的request.GET,为了遵循restful规范
-requset.FILES :新的
-重写了__getattr__,新的request.原来所有的属性和方法,都能直接拿到
def __getattr__(self, attr):
return getattr(self._request, attr)
Five, serialization component introduction
1. Serialization
The serializer will convert the model object into a dictionary, and program the json string after the response
2. Deserialization
What Buckhuadan sends is data, which becomes a dictionary after request. The serializer can convert the dictionary into a model
json format data----drf: request---->Dictionary—Serializer—>Book
3. Deserialization, complete data verification function
Six, easy to use serialization group
1. Create a serialized py file
serializer.py
2. Write a class that inherits serializers.Serializer, and write the fields to be serialized in the class
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(required=True)
name = serializers.CharField(max_length=32, min_length=3)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
publish = serializers.CharField(max_length=10)
3. Related
# modles.py
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.CharField(max_length=32)
# views.py
class Book(APIView):
# get 接口 用来查询所有
def get(self, request, *args, **kwargs):
result = models.Book.objects.all()
# 借助序列化器
# 如果是多条,就是many=True
# 如果是单个对象,就不写
ser = serializer.BookSerializer(instance=result, many=True)
print(type(ser)) # rest_frameword.serializers.ListSerializer
print(ser.data) # 得到的是一个通过序列器的字典
return Response(ser.data) # 这是使用的是自己的Response
# urls.py
url(r'^book/', views.Book.as_view()),
Seven, serialization class field types and field parameters
Field type (the following key points)
- IntegerField
- CharField
- DecimalField
- DateTimeField
- …So many are similar to those in models
Common field parameters
Option parameter
- max_length maximum length
- min_length minimum length
- Whether allow_blank is allowed to be empty (generally not used)
- trim_whitespace Whether to cut off white space characters (generally not equivalent to sprip)
- max_value maximum
- min_value minimum
General parameters
Focus
- read_only indicates that the field is only used for serialized output, the default is False
- write_only indicates that the field is only used for deserializing input, the default is False
grasp
- required indicates that the field must be entered during deserialization, the default is True
- default The default value used when deserializing
- allow_null indicates whether the field is allowed to pass in None, the default is False
To understanding
- validators the validators used by the field
- error_messages A dictionary containing error numbers and error messages
8. Save function of serializer
def post(self, request):
print(request.data)
# 反序列化后的数据
ser = serializer.BookSerializer(data=request.data)
if ser.is_valid(): # 校验数据是否可用
ser.save() # 保存到数据库(仅仅是save无法保存 要在序列化类中 写一个create方法)
# 根据resful规范 返回数据 返回新生成的资源对象 (新增后的对象字典)
return Response(ser.data)
else:
# 返回错误信息
return Response(ser.errors)
Then we use postman to simulate the request
The backend got the data but reported a create error
Now we implement the create method
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(required=False)
name = serializers.CharField(max_length=32, min_length=3)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
publish = serializers.CharField(max_length=10)
def create(self, validated_data):
# 创建对象 validated_data 校验后的数据
result = models.Book.objects.create(**validated_data)
print(result)
return result # 最后把结果返回
Send the request again
There is also data in the database
Nine, the field verification function of the serializer
We mentioned in the field parameters
validators 该字段使用的验证器
Now let's use it
def length_limit(data):
if data.startswith('xxx'):
raise ValidationError('名字不能以xxx开头')
else:
return data
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(required=False)
# 给名字添加 长度限制
name = serializers.CharField(max_length=32, min_length=3, validators=[length_limit, ])
price = serializers.DecimalField(max_digits=5, decimal_places=2)
publish = serializers.CharField(max_length=32)
def create(self, validated_data):
# 创建对象 validated_data 校验后的数据
result = models.Book.objects.create(**validated_data)
print(result)
return result # 最后把结果返回
# 局部钩子
# z这里与form表单不同的是 局部钩子 所带的参数 就是要校验参数 不用取值
def validate_price(self, data):
if data > 20:
raise ValidationError('定价过高')
else:
return data
# 全局钩子
# 与 form 表单用法相同
def validate(self, attrs):
name = attrs.get('name')
publish = attrs.get('publish')
if name == publish:
raise ValidationError('书名不能和出版社同名!')
else:
return attrs
Let's use postman to test
These are the three functions of the check field
- Field’s own validation rules (max_length...)
- validation of validators
- 'hook'
十、read_only和write_only
read_only indicates that the field is only used for serialized output, the default is False
id = serializers.IntegerField(required=False)
# 给名字添加 长度限制
name = serializers.CharField(max_length=32, min_length=3, validators=[length_limit, ], read_only=True)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
publish = serializers.CharField(max_length=32)
So when we send and write data in the post , the name field is not written into the database, so this record is not seen in the returned data , because it isRead onlyof
write_only indicates that the field is only used for deserializing input, the default is False
We add to publish just write Then we can’t see this field when we get the request
id = serializers.IntegerField(required=False)
# 给名字添加 长度限制
name = serializers.CharField(max_length=32, min_length=3, validators=[length_limit, ])
price = serializers.DecimalField(max_digits=5, decimal_places=2)
publish = serializers.CharField(max_length=32, write_only=True)
Postman simulates sending a get request, it really doesn't!