drf序列化组件
models
from django.db import models # Create your models here. class Book(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) publish_date = models.DateField() publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE) authors = models.ManyToManyField(to='Author') def __str__(self): return self.name class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() author_detail = models.OneToOneField(to='AuthorDatail', to_field='nid', unique=True, on_delete=models.CASCADE) class AuthorDatail(models.Model): nid = models.AutoField(primary_key=True) telephone = models.BigIntegerField() birthday = models.DateField() addr = models.CharField(max_length=64) class Publish(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name def test(self): return self.email
views
from django.shortcuts import render from django.http import JsonResponse # Create your views here. from rest_framework.views import APIView from app01 import models from app01.myser import BookSerializer class Books(APIView): def get(self, request, *args, **kwargs): book = models.Book.objects.all() book_ser = BookSerializer(book, many=True) print(book_ser.data) return JsonResponse(book_ser.data, safe=False)
myser
from rest_framework import serializers class AuthorSerializer(serializers.Serializer): name = serializers.CharField() age = serializers.CharField() telephone = serializers.CharField(source='author_detail.telephone') # class BookSerializer(serializers.Serializer): # # 可以用source修改别名,如果不指定source,字段必须对应起来,如果指定了source,字段可以任意命名 # xx = serializers.CharField(source='name') # price = serializers.CharField() # sb = serializers.CharField(source='publish.city') #source 可以指定字段,也可也指定方法,publish.test这是个方法,会执行该方法,并拿到返回结果 # test = serializers.CharField(source='publish.test') # publish_id = serializers.CharField() # # SerializerMethodField,可以指定一个方法 # # publish=serializers.SerializerMethodField() # # # 方法名:叫get_字段名,要传参数,参数是:当前book对象 # # def get_publish(self,obj): # # # obj 是当前book对象0 # # dic={'name':obj.publish.name,'email':obj.publish.email} # # return dic # authors=serializers.SerializerMethodField() # # def get_authors(self,book): # # #拿到这本书的所有作者 # # aus=book.authors.all() # # # 拼出一个列表,列表中套字典,每个字典是一个作者 # # ll=[] # # for a in aus: # # ll.append({'name':a.name,'age':a.age}) # # return ll # def get_authors(self,book): # #拿到这本书的所有作者 # aus=book.authors.all() # # 可以继续用序列化类,来处理 # auth_ser=AuthorSerializer(aus,many=True) # return auth_ser.data from ap01.models import Book # class BookSerializer(serializers.ModelSerializer): # # 必须写一个内部类,名字叫Meta # class Meta: # model = Book # fields = '__all__' # # 重写属性 # publish = serializers.CharField(source='publish.name') # authors = serializers.SerializerMethodField() # def get_authors(self, book): # # 拿到这本书的所有作者 # aus = book.authors.all() # # 可以继续用序列化类,来处理 # auth_ser = AuthorSerializer(aus, many=True) # return auth_ser.data class BookSerializer(serializers.ModelSerializer): # 必须写一个内部类,名字叫Meta class Meta: model = Book # fields = '__all__' # 指定只取这两个字段 fields = ['nid','name'] # 去掉指定的字段 # exclude=['publish','authors'] # fields,跟exclude不能连用 # 指定深度(官方建议小于10,个人建议小于3) # depth = 2
生成HyperlinkedIdentityField链接
-1 publish = serializers.HyperlinkedIdentityField(view_name='ttt',lookup_field='publish_id',lookup_url_kwarg='pky') -2 view_name:路由的别名,lookup_field:根据表的哪个字段,来拼路径,lookup_url_kwarg:反向解析有名分组的名字 -3 写路由:url(r'^publish/(?P<pky>\d+)', views.Publish.as_view(),name='ttt'), -4 实例化序列化类的时候,需要把request对象传过去 book_ser=BookSerializer(ret,many=True,context={'request': request}) class BookSerializers(serializers.ModelSerializer): class Meta: model = models.Book fields = "__all__" # 生成连接,直接查看出版社详情 publish = serializers.HyperlinkedIdentityField(view_name='ttt', lookup_field='publish_id', lookup_url_kwarg='pkk') authors=serializers.SerializerMethodField() def get_authors(self,obj): ret=obj.authors.all() ss=AuthorSerializer(ret,many=True) return ss.data #-------------- res=BookSerializers(ret,many=True,context={'request': request}) #-------------- class Publish(APIView): def get(self,request,pkk): print(pkk ) return HttpResponse('ok') #----路由--- url(r'^publish/(?P<pkk>\d+)$', views.Publish.as_view(),name='ttt'),
序列化组件之请求数据校验和保存修改功能
from rest_framework.exceptions import ValidationError class BookSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = '__all__' #字段是否必填,通过required控制,min_length最短是2, error_messages内控制错误信息显示中文 name = serializers.CharField(min_length=2, error_messages={'required': '该字段必填'}) authors = serializers.CharField(required=False) # 局部钩子: def validate_name(self, value): # value是Book表的name if value.startswith('sb'): # 不能以sb开头 raise ValidationError('不能以sb开头') elif Book.objects.filter(name=value).first(): raise ValidationError('已存在的名字') else: return value # 全局钩子 def validate(self, value): # value是所有校验通过数据的字典 print(value) name = value.get('name') price = value.get('price') if name and price: if str(name) == str(price): return value else: raise ValidationError('名字跟价格不相等') return value
class Books(APIView): def get(self, request, *args, **kwargs): ret = models.Book.objects.all() # 生成一个序列化的对象,传参数 # 序列化多条,记住many=True book_ser = BookSerializer(ret, many=True, context={'request': request}) print(book_ser.data) return JsonResponse(book_ser.data, safe=False) def post(self, request, *args, **kwargs): # 前端传递过来的数据从data中取 # 用序列化类的数据校验 # data参数,是要校验的数据 response = {'status': 100, 'msg': '成功'} ser = BookSerializer(data=request.data) if ser.is_valid(): # 如果数据校验通过,is_valid是True # 保存到数据库,ser是谁的对象?继承了ModelSerializer的类的对象 ser.save() else: response['status'] = 101 response['msg'] = ser.errors return JsonResponse(response, safe=False)
class BooksDetail(APIView): authentication_classes = [Auth, ] def get(self, request, pk): response = {'status': 100, 'msg': '成功'} ret = models.Book.objects.all().filter(pk=pk).first() # 生成一个序列化的对象,传参数 # 序列化单,记住many=False if ret: book_ser = BookSerializer(ret, many=False) print(book_ser.data) response['data'] = book_ser.data else: response['status'] = 101 response['msg'] = '您查询的不存在' return JsonResponse(response, safe=False) def put(self, request, pk): response = {'status': 100, 'msg': '成功'} ret = models.Book.objects.all().filter(pk=pk).first() if ret: # 数据校验 # 传instance和不传instance,传instance的区别 # 不传instance,调save(),往数据库新增数据 # 传instance,调save(),修改数据 ser = BookSerializer(data=request.data, instance=ret) if ser.is_valid(): # ret.name=request.data.get('name') ser.save() else: response['status'] = 101 response['msg'] = ser.errors else: response['status'] = 102 response['msg'] = '修改的对象不存在' return JsonResponse(response, safe=False)