一:表关系如下
from django.db import models
# Create your models here.
__all__=['Book','Publisher','Authon']
class Book(models.Model):
title =models.CharField(max_length=32,verbose_name='图书名称')
CHOICES=((1,'python'),(2,'go'),(3,'linux'))
category=models.IntegerField(choices=CHOICES,verbose_name='图书类别')
pub_time=models.DateTimeField(verbose_name='出版日期')
authon=models.ManyToManyField('Authon')
publisher=models.ForeignKey(to='Publisher',on_delete=None)
def __str__(self):
return self.title
class Authon(models.Model):
name= models.CharField(max_length=32, verbose_name='作者姓名')
def __str__(self):
return self.name
class Publisher(models.Model):
title = models.CharField(max_length=32, verbose_name='出版社名称')
def __str__(self):
return self.title
二:使用django编写接口
1:使用jsonResponse模块进行数据序列化。
from django.http import JsonResponse
class Bookview(View):
#使用jsonResponse 当存在外键时,需要自己手动对数据进行处理。
def get(self,request):
book_list=models.Book.objects.values('id','title','pub_time','publisher',"category")
book_list=list(book_list)
for book in book_list:
print(book)
publisher_id = book['publisher']
publisher_obj=models.Publisher.objects.filter(id=publisher_id).first()
book['pulisher']={
'id':publisher_id,
'title':publisher_obj.title
}
return JsonResponse(book_list,safe=False,json_dumps_params={'ensure_ascii':False})
2:使用serialize模块进行数据序列化。
def get(self,request):
book_list=models.Book.objects.all()
book_list=serializers.serialize('json',book_list,ensure_ascii=False )
return HttpResponse(book_list)
3:使用serialize和JsonResponse不方便处
a:遇到外键关系,需要非常繁琐的处理。
三:使用rest_framework 中 serializers进行序列化和反序列化
1:基本准备
a:下载 rest-framewoke模块,pip install rest-framework
b:首先要明白后端展示给前端页面的数据,可能是经过跨表查询的具体值。而前端传送给后端,并不需要传送具体的值,也就是说前端和后端对同一个资源传递的数据类型可能不一样。比如性别,前端展示的是,男,女。但是后端在数据库存储的时候,往往是0,1
c:新建文件serializers.py(用于编写序列化规则)
d:settings中注册app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'SerDemo',
'rest_framework' #app注册
]
2:serializers序列化
a:设定路由
--注意需要调用as_view方法
from django.urls import path,include
from SerDemo import views
urlpatterns = [
path('list/', views.BookApiView.as_view()),
]
b:在serializes.py编写序列化规则
--注意序列化规则内每一个字段都和models字段相对应。重点,
--外键关系一对多和多对多需要注意
--read_only=True(只进行序列化),同理write_only=True(该字段只进行反序列化)
from rest_framework import serializers
from SerDemo.models import Book
#一对多外键关系序列化处理
class PublisherSerializers(serializers.Serializer):
id = serializers.IntegerField()
title=serializers.CharField(max_length=32)
#多对多外键关系序列化处理
class AuthonSerializers(serializers.Serializer):
id = serializers.IntegerField()
name=serializers.CharField(max_length=32)
class BookSerializers(serializers.Serializer):
#不需要校验
id = serializers.IntegerField(required=False,)
title = serializers.CharField(max_length=32)
CHOICES = ((1, 'python'), (2, 'go'), (3, 'linux'))
category = serializers.ChoiceField(choices=CHOICES, source="get_category_display",read_only=True)
pub_time = serializers.DateTimeField()
#处理一对多
publisher=PublisherSerializers(read_only=True)
#处理多对多外键关系 many=True
authon=AuthonSerializers(many=True,read_only=True)
c:视图函数的编写
--导包 (APIView,Response)
--视图函数继承APIView
--many默认参数不写默认序列化一个对象,many=True 表示序列化多个对象
--get请求会对应get方法
from SerDemo import models
from rest_framework.views import APIView #视图函数继承APIView 不是View
from rest_framework.response import Response #用于返回值
#BookSerializers 自己定义的序列化规则
from SerDemo.serializers import *
class BookApiView(APIView):
def get(self,request):
book_obj = models.Book.objects.all()
#序列化多组数据 和一个对象,需要many=TRUE 默认一个
ret =BookSerializers(book_obj,many=True)
#序列化的数据在data属性中
return Response(ret.data)
3:serializers反序列化
a:在serializes.py编写反序列化规则
--首先序列化,我们常常需要把外键对象的值获取给前端,而反序列化,后端仅仅需要数据库一个id就能进行数据库值的插入。
--write_only表示该字段只是反序列化使用,前端发送时key也应该和该值对应
--注意一对多,多对多关系,choices的字段
class BookSerializers(serializers.Serializer):
#不需要校验
id = serializers.IntegerField(required=False,)
title = serializers.CharField(max_length=32,validators=[my_validata])
CHOICES = ((1, 'python'), (2, 'go'), (3, 'linux'))
category = serializers.ChoiceField(choices=CHOICES, source="get_category_display",read_only=True)
w_category=serializers.ChoiceField(choices=CHOICES,write_only=True)
pub_time = serializers.DateTimeField()
#处理一对多
publisher=PublisherSerializers(read_only=True)
publisher_id=serializers.IntegerField(write_only=True)
#处理多对多外键关系 many=True
authon=AuthonSerializers(many=True,read_only=True)
authon_id =serializers.ListField(write_only=True)
b:views文件中编写post的请求,对数据进行添加。
--添加数据需要在BookSerializers重新编写create方法
--注意返回值
--所有的数据都在request.data方法中,(与View方法存在request.get,request.post中不同,该方法对这些方法进行封装)
def post(self,request):
# print(request.data)
data = BookSerializers(data=request.data)
#进行数据验证,并且在BookSerializers中重写create方法
if data.is_valid():
data.save()
return Response(data.data)
else:
return Response(data.errors)
c:编写create方法
class BookSerializers(serializers.Serializer):
#不需要校验
id = serializers.IntegerField(required=False,)
title = serializers.CharField(max_length=32,validators=[my_validata])
CHOICES = ((1, 'python'), (2, 'go'), (3, 'linux'))
category = serializers.ChoiceField(choices=CHOICES, source="get_category_display",read_only=True)
w_category=serializers.ChoiceField(choices=CHOICES,write_only=True)
pub_time = serializers.DateTimeField()
#处理一对多
publisher=PublisherSerializers(read_only=True)
publisher_id=serializers.IntegerField(write_only=True)
#处理多对多外键关系 many=True
authon=AuthonSerializers(many=True,read_only=True)
authon_id =serializers.ListField(write_only=True)
#向服务器添加数据,需要实现该方法
def create(self, validated_data):
book =Book.objects.create(title=validated_data['title'],category=validated_data['w_category'],
pub_time=validated_data['pub_time'],
publisher_id=validated_data['publisher_id']
)
#添加多对多关系
book.authon.add(*validated_data['authon_id'])
return book
d:put实现更新
--路由分发 path('retrieve/<int:id>',views.BookEditView.as_view())
--代码编写
--partial参数
def put(self,request,id):
print(request.data)
book_obj = Book.objects.filter(id=id).first()
# partial True 表示可以进行部分字段跟新,Flase 表示全部跟新,默认False
book_serializers = BookSerializers(book_obj,data=request.data,partial=True)
#需要重写 update
if book_serializers.is_valid():
book_serializers.save()
return Response(book_serializers.validated_data)
else:
return Response(book_serializers.errors)
--重写update方法
#数据跟新
def update(self, instance, validated_data):
print(validated_data.get('authon'))
instance.title =validated_data.get('title',instance.title)
instance.category=validated_data.get('category',instance.category)
instance.pub_time =validated_data.get('pub_time',instance.pub_time)
instance.publisher_id =validated_data.get('publisher_id',instance.publisher_id)
if validated_data.get('authon_id'):
instance.authon.set(validated_data.get('authon_id'))
instance.save()
return instance
e:实现delete方法
def delete(self,request,id):
book_obj = Book.objects.filter(id=id).first()
book_obj.delete()
return Response("")
4:serializers字段校验扩展
a:局部钩子校验
--校验字段方法,固定格式validate_字段名
-- 参数value,就是该字段的值
-- 返回值
#单个字段进行校验
def validate_title(self, value):
if 'python' not in value.lower:
return serializers.ValidationError('标题必须含有python')
return value
b:全局钩子多个字段联合校验
--方法 validate为固定方法
--attrs保存联合字段的字段值
--注意返回值
#全局钩子对字段进行联合校验
def validate(self, attrs):
if attrs['category'] =='linux' and attrs['publisher_id']==3:
return attrs
else:
return serializers.ValidationError('类型或出版社错误')
c:自定义钩子验证
#自定义校验
#在需要进行验证的字段引用 title = serializers.CharField(max_length=32,validators=[my_validata])
#优先级大于 validata_title 局部钩子
def my_validata(value):
if value in '敏感信息':
raise serializers.ValidationError('不能含有敏感信息')
return value
来源:oschina
链接:https://my.oschina.net/u/4280449/blog/3597360