一、序列化 1.步骤
model s.py,定义表与字段,及表关系
serializes.py 中序列化与反序列化
views.py 中写 get,post 等操作
urls.py 定义路由
2.模拟场景 建立图书管理系统: 表Book: name, price, img, authors, publish, is_delete, create_time 表Publish: name, address, is_delete, create_time 表Author: name, age, is_delete, create_time 表AuthorDetail: mobile, author, is_delete, create_time
3.模型构建 modes.py
from django.db import modelsfrom django.contrib.auth.models import Userclass BaseModel (models.Model): is_delete = models.BooleanField(default=0 ) create_time = models.DateTimeField(auto_now_add=True ) class Meta : abstract = True class Book (BaseModel ): name = models.CharField(max_length=64 ) price = models.DecimalField(max_digits=5 , decimal_places=2 ) img = models.ImageField(upload_to='img' , default='img/default.jpg' ) publish = models.ForeignKey( to='Publish' , db_constraint=False , related_name='books' , on_delete=models.DO_NOTHING ) authors = models.ManyToManyField( to='Author' , db_constraint=False , related_name='books' ) @property def publish_name (self ): return self.publish.name @property def author_list (self ): return self.authors.values('name' , 'age' , 'detail__mobile' ).all () class Meta : db_table = 'book' verbose_name = '书籍' verbose_name_plural = verbose_name def __str__ (self ): return self.nameclass Publish (BaseModel ): name = models.CharField(max_length=64 ) address = models.CharField(max_length=64 ) class Meta : db_table = 'publish' verbose_name = '出版社' verbose_name_plural = verbose_name def __str__ (self ): return f'{self.name} ' class Author (BaseModel ): name = models.CharField(max_length=64 ) age = models.IntegerField() class Meta : db_table = 'author' verbose_name = '作者' verbose_name_plural = verbose_name def __str__ (self ): return f'{self.name} ' class AuthorDetail (BaseModel ): mobile = models.CharField(max_length=11 ) author = models.OneToOneField( to='Author' , db_constraint=False , related_name='detail' , on_delete = models.CASCADE, ) class Meta : db_table = 'author_detail' verbose_name = '作者详情' verbose_name_plural = verbose_name def __str__ (self ): return f'from django.db import modelsfrom django.contrib.auth.models import Userclass BaseModel (models.Model): is_delete = models.BooleanField(default=0 ) create_time = models.DateTimeField(auto_now_add=True ) class Meta : abstract = True class Book (BaseModel ): name = models.CharField(max_length=64 ) price = models.DecimalField(max_digits=5 , decimal_places=2 ) img = models.ImageField(upload_to='img' , default='img/default.jpg' ) publish = models.ForeignKey( to='Publish' , db_constraint=False , related_name='books' , on_delete=models.DO_NOTHING ) authors = models.ManyToManyField( to='Author' , db_constraint=False , related_name='books' ) @property def publish_name (self ): return self.publish.name @property def author_list (self ): return self.authors.values('name' , 'age' , 'detail__mobile' ).all () class Meta : db_table = 'book' verbose_name = '书籍' verbose_name_plural = verbose_name def __str__ (self ): return self.nameclass Publish (BaseModel ): name = models.CharField(max_length=64 ) address = models.CharField(max_length=64 ) class Meta : db_table = 'publish' verbose_name = '出版社' verbose_name_plural = verbose_name def __str__ (self ): return f'{self.name} ' class Author (BaseModel ): name = models.CharField(max_length=64 ) age = models.IntegerField() class Meta : db_table = 'author' verbose_name = '作者' verbose_name_plural = verbose_name def __str__ (self ): return f'{self.name} ' class AuthorDetail (BaseModel ): mobile = models.CharField(max_length=11 ) author = models.OneToOneField( to='Author' , db_constraint=False , related_name='detail' , on_delete = models.CASCADE, ) class Meta : db_table = 'author_detail' verbose_name = '作者详情' verbose_name_plural = verbose_name def __str__ (self ): return f'{self.author} 的详情'
4.序列化 serializes.py
from rest_framework import serializersfrom rest_framework.exceptions import ValidationErrorfrom rest_framework.fields import SerializerMethodFieldfrom rest_framework.serializers import ModelSerializerfrom api import modelsclass PublishModelSerializer (ModelSerializer ): class Meta : model = models.Publish fields = ('name' , 'address' )class BookModelSerializers (ModelSerializer ): publish = PublishModelSerializer() class Meta : model = models.Book fields = ('name' , 'price' , 'img' ,'author_list' , 'publish' )
5.视图 views.py
from django.shortcuts import renderfrom rest_framework.response import Responsefrom rest_framework.views import APIViewfrom api import models, serializersclass Book (APIView ): def get (self, request, *args, **kwargs ): pk = kwargs.get('pk' ) if pk: try : book_obj = models.Book.objects.get(pk=pk) book_data = serializers.BookModelSerializers(book_obj).data except : return Response({ 'status' : 1 , 'msg' : 'Books does not exist' }) else : book_objs = models.Book.objects.all () book_data = serializers.BookModelSerializers(book_objs, many=True ).data return Response({ 'status' : 0 , 'msg' : 'ok' , from django.shortcuts import renderfrom rest_framework.response import Responsefrom rest_framework.views import APIViewfrom api import models, serializersclass Book (APIView ): def get (self, request, *args, **kwargs ): pk = kwargs.get('pk' ) if pk: try : book_obj = models.Book.objects.get(pk=pk) book_data = serializers.BookModelSerializers(book_obj).data except : return Response({ 'status' : 1 , 'msg' : 'Books does not exist' }) else : book_objs = models.Book.objects.all () book_data = serializers.BookModelSerializers(book_objs, many=True ).data return Response({ 'status' : 0 , 'msg' : 'ok' , 'results' : book_data })
6.路由 urls.py
from django.contrib import adminfrom django.urls import pathfrom django.conf.urls import url, includefrom django.views.static import servefrom django.conf import settingsfrom api import views urlpatterns = [ url(r'^books/$' , views.Book.as_view()), url(from django.contrib import adminfrom django.urls import pathfrom django.conf.urls import url, includefrom django.views.static import servefrom django.conf import settingsfrom api import views urlpatterns = [ url(r'^books/$' , views.Book.as_view()), url(r'^books/(?P.*)/$' , views.Book.as_view()), ]
7.测试接口 使用 GET 查询结果
二、反序列化与验证 1.反序列化 serializers.py
class BookModelDeserializers (ModelSerializer ): class Meta : model = models.Book fields = ('name' , 'price' ,'publish' , 'authors' ) extra_kwargs = { 'name' : { 'required' : True , 'max_length' : 5 , 'error_messages' : { 'required' : 'name field is required.' , 'max_length' : 'too long' } }, } def validate_name (self, attrs ): if 'tmd' in attrs.lower(): raise ValidationError('tmd error' ) return attrs def validate (self, attrs ): publish = attrs.get('publish' ) name = attrs.get('name' ) if models.Book.objects.filter (name=name, publish=publish): raise ValidationError({'book' : 'Book exist.' }) class BookModelDeserializers (ModelSerializer ): class Meta : model = models.Book fields = ('name' , 'price' ,'publish' , 'authors' ) extra_kwargs = { 'name' : { 'required' : True , 'max_length' : 5 , 'error_messages' : { 'required' : 'name field is required.' , 'max_length' : 'too long' } }, } def validate_name (self, attrs ): if 'tmd' in attrs.lower(): raise ValidationError('tmd error' ) return attrs def validate (self, attrs ): publish = attrs.get('publish' ) name = attrs.get('name' ) if models.Book.objects.filter (name=name, publish=publish): raise ValidationError({'book' : 'Book exist.' }) return attrs
2.视图 views.py
from django.shortcuts import renderfrom rest_framework.response import Responsefrom rest_framework.views import APIViewfrom api import models, serializersclass Book (APIView ): def get (self, request, *args, **kwargs ):... def post (self, request, *args, **kwargs ): request_data = request.data book_ser = serializers.BookModelDeserializers(data=request_data) book_ser.is_valid(raise_exception=True ) book_obj = book_ser.save() return Response({ 'status' : 0 , 'msg' : 'ok' , from django.shortcuts import renderfrom rest_framework.response import Responsefrom rest_framework.views import APIViewfrom api import models, serializersclass Book (APIView ): def get (self, request, *args, **kwargs ):... def post (self, request, *args, **kwargs ): request_data = request.data book_ser = serializers.BookModelDeserializers(data=request_data) book_ser.is_valid(raise_exception=True ) book_obj = book_ser.save() return Response({ 'status' : 0 , 'msg' : 'ok' , 'results' : serializers.BookModelSerializers(book_obj).data })
3.测试接口 使用 POST 第一次正常入库
敏感字验证
书名重复验证
三、序列化与反序列的整合 从数据的安全性和健壮性来考虑,所有的自定义字段不能与 model 的原字段相同
因为序列化是将外键字段作为 Dict,而反序列化会将外键字段作为 Object
1.视图 views.py
...class BookV2 (APIView ): def get (self, request, *args, **kwargs ): pk = kwargs.get('pk' ) if pk: try : book_obj = models.Book.objects.get(pk=pk) book_data = serializers.BookV2ModelSerializer(book_obj).data except : return Response({ 'status' : 0 , 'msg' : 'Books do not existed' }) else : book_obj = models.Book.objects.all () book_data = serializers.BookV2ModelSerializer(book_obj, many=True ).data return Response({ 'status' : 0 , 'msg' : 'ok' , 'results' : book_data }) def post (self, request, *args, **kwargs ): request_data = request.data book_ser = serializers.BookV2ModelSerializer(data=request_data) book_ser.is_valid(raise_exception=True ) book_obj = book_ser.save() return Response({ 'status' : 100 , 'msg' : 'ok' , ...class BookV2 (APIView ): def get (self, request, *args, **kwargs ): pk = kwargs.get('pk' ) if pk: try : book_obj = models.Book.objects.get(pk=pk) book_data = serializers.BookV2ModelSerializer(book_obj).data except : return Response({ 'status' : 0 , 'msg' : 'Books do not existed' }) else : book_obj = models.Book.objects.all () book_data = serializers.BookV2ModelSerializer(book_obj, many=True ).data return Response({ 'status' : 0 , 'msg' : 'ok' , 'results' : book_data }) def post (self, request, *args, **kwargs ): request_data = request.data book_ser = serializers.BookV2ModelSerializer(data=request_data) book_ser.is_valid(raise_exception=True ) book_obj = book_ser.save() return Response({ 'status' : 100 , 'msg' : 'ok' , 'results' : serializers.BookV2ModelSerializer(book_obj).data })
2.路由 urls.py
from django.conf.urls import url, includefrom api import views urlpatterns = [ url(r'^books/$' , views.Book.as_view()), url(r'^books/(?P<pk>.*)/$' , views.Book.as_view()), url(r'^v2/books/$' , views.BookV2.as_view()), url(from django.conf.urls import url, includefrom api import views urlpatterns = [ url(r'^books/$' , views.Book.as_view()), url(r'^books/(?P<pk>.*)/$' , views.Book.as_view()), url(r'^v2/books/$' , views.BookV2.as_view()), url(r'^v2/books/(?P.*)/$' , views.BookV2.as_view()), ]
3.接口测试 序列化演示
反序列化演示