rest-framework序列化之Serializer
models.py
from django.db import models# Create your models here.class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") authors=models.ManyToManyField("Author") def __str__(self): return self.titleclass Publish(models.Model): name=models.CharField(max_length=32) email=models.EmailField() def __str__(self): return self.nameclass Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() def __str__(self): return self.name
view部分:
from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom .models import *from django.shortcuts import HttpResponsefrom django.core import serializers # django 自带的序列化组件from rest_framework import serializersclass BookSerializers(serializers.Serializer): title=serializers.CharField(max_length=32) price=serializers.IntegerField() pub_date=serializers.DateField() publish=serializers.CharField(source="publish.name") #authors=serializers.CharField(source="authors.all") authors=serializers.SerializerMethodField() def get_authors(self,obj): temp=[] for author in obj.authors.all(): temp.append(author.name) return temp #此处可以继续用author的Serializers, # def get_authors(self,obj): # ret=obj.authors.all() # ss=AuthorSerializer(ret,many=True) # return ss.dataclass BookViewSet(APIView): def get(self,request,*args,**kwargs): book_list=Book.objects.all() # 序列化方式1: # from django.forms.models import model_to_dict # import json # data=[] # for obj in book_list: # data.append(model_to_dict(obj)) # print(data) # return HttpResponse("ok") # 序列化方式2: # data=serializers.serialize("json",book_list) # return HttpResponse(data) # 序列化方式3: bs=BookSerializers(book_list,many=True) #many=True代表有多条数据,如果只有一条数据,many=False return Response(bs.data) # 序列化方式4: # ret=models.Book.objects.all().values('nid','title') # dd=list(ret) # return HttpResponse(json.dumps(dd))
注意:
source 如果是字段,会显示字段,如果是方法,会执行方法,不用加括号(authors=serializers.CharField(source='authors.all'))
如在模型中定义一个方法,直接可以在在source指定执行
class UserInfo(models.Model): user_type_choices = ( (1,'普通用户'), (2,'VIP'), (3,'SVIP'), ) user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32,unique=True) password = models.CharField(max_length=64)#视图ret=models.UserInfo.objects.filter(pk=1).first()aa=ret.get_user_type_display()#serializerxx=serializers.CharField(source='get_user_type_display')
rest-framework序列化之ModelSerializer
urls.py
"""Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))"""from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^books/(?P\d*)',views.Book.as_view())]
models.py
from django.db import models# Create your models here.class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) publish_time = models.DateTimeField(auto_now_add=True) # 自动添加创建时间 authors = models.ManyToManyField('Author') publish = models.ForeignKey('Publish') # 一对多 def test(self): return self.title+'>>'+str(self.price)class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() authordetail = models.OneToOneField('AuthorDetail')class AuthorDetail(models.Model): tel_num = models.BigIntegerField() addr = models.CharField(max_length=32)class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) email = models.EmailField()
"""序列化的类"""# -*- coding: utf-8 -*-# 想序列化Book 就要给其写一个序列化的类from rest_framework import serializersfrom rest_framework.exceptions import ValidationError# class BookSerializer(serializers.Serializer):# id = serializers.CharField()# title = serializers.CharField()# price = serializers.CharField()# publish = serializers.CharField() # 不使用source的时候,可以与表中的字段名相同# publish1 = serializers.CharField(source='publish') # 字段名不能与前面的序列化的名字一样, 在使用source的时候# publish_name = serializers.CharField(source='publish.name') # 跨表获取字段属性的值# publish_pk = serializers.CharField(source='publish.pk') # 跨表# # test1 = serializers.CharField(source='test') # 方法## # 支持写方法,如下:# # 方法一定要传一个参数,是当前被序列化的book对象# publish_dic = serializers.SerializerMethodField()## def get_publish_dic(self, obj):# # 这里的obj就是当前book对象# return {'id': obj.publish.id, 'name': obj.publish.name}from app01 import modelsclass AuthorSerializer(serializers.Serializer): id = serializers.CharField() name = serializers.CharField() age = serializers.CharField()# ModelSerializer 是与表模型绑定的 Serializerclass BookSerializer(serializers.ModelSerializer): class Meta: # 指定表模型 model = models.Book fields = '__all__' # 表示我要序列化所有字段 # # 只序列化 title 和 id 两个字段 # fields = ['title','id'] # 其他字段都需要 ,剔除price字段 # exclude = ['price'] # 该方法和 fields 不能一起用 # 如果想让publish字段显示出版社的名字 # 跨表深度(连表的深度) 不建议使用,因为下几层的参数无法控制,官方建议不超过十层,实际使用不要超过3 depth = 1 # publish = serializers.CharField(source='publish.name') authors = serializers.SerializerMethodField() def get_authors(self, obj): authors_list = obj.authors.all() authors_serializer = AuthorSerializer(authors_list, many=True) return authors_serializer.data title = serializers.CharField(max_length=6,min_length=3,error_messages={'max_length':'太长了','min_length':'你太短了'}) # 局部钩子 # from rest_framework.exceptions import ValidationError --->导入报错信息 def validate_title(self, value): print(value) # 是 title 说对应的值 if value.startswith('sb'): raise ValidationError('不能以sb开头') return value # 全局钩子 def validate(self, attrs): print(attrs) # 这里的attrs 是一个字典 {'title': 'bbb123', 'price': '999.12', 'authors': 2, 'publish': 2} if attrs.get('title').startswith('bbb')and attrs.get('price')>120: raise ValidationError('太贵啦,bbb书籍') return attrs
"""views.py"""from django.shortcuts import renderfrom django.http.response import JsonResponse# Create your views here.from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom app01 import modelsfrom app01.myser import BookSerializerclass Book(APIView): # get 获取所有书籍信息 def get(self, request, id): response = {'status': 100, 'msg': '成功'} print(id) if not id: book_list = models.Book.objects.all() # 第一个参数是要序列化的queryset对象,如果要序列化多条,必须制定many=True # 当instance形参被传入的实参是单个参数的时候,many=False book_serializer = BookSerializer(book_list, many=True) else: print(id) book_obj = models.Book.objects.filter(pk=id).first() book_serializer = BookSerializer(book_obj, many=False) print(book_serializer.data) response['books'] = book_serializer.data return Response(response) def post(self, request, id): response = {'status': 100, 'msg': '成功'} # 提交的字典 book = request.data # 传统方法,创建对象保存 print(book) # 新方法,通过序列化组件保存,必须继承自ModelSerializer book_ser = BookSerializer(data=book) # is_valid 提交的字段校验通过 if book_ser.is_valid(): book_ser.save() response['book'] = book_ser.data else: response['msg'] = book_ser.errors # errors 是序列化类 中的钩子函数 raise来的报错信息 return Response(response) def put(self, request, id): response = {'status': 100, 'msg': '修改成功'} if id: # 提交的字典 book = request.data # 传统方法,创建对象保存 print(book) book_obj = models.Book.objects.filter(pk=id).first() # 新方法,通过序列化组件保存,必须继承自ModelSerializer book_ser = BookSerializer(data=book, instance=book_obj) # is_valid 提交的字段校验通过 if book_ser.is_valid(): # 这里save()做修改 book_ser.save() response['book'] = book_ser.data else: response['msg'] = book_ser.errors else: response['msg'] = '修改对象不存在' return Response(response) def delete(self, request, id): models.Book.objects.filter(pk=id).delete() response = {'status': 100, 'msg': '删除成功'} return Response(response)