rest_framework - Serializers
APIView
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.title class Publish(models.Model): name = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() def __str__(self): return self.name class User(models.Model): user = models.CharField(max_length=32) pwd = models.CharField(max_length=32) user_type = models.IntegerField(choices=((1, "普通用户"), (2, "VIP"), (3, "sVIP")), default=1) class UserToken(models.Model): user = models.OneToOneField(to="user") token = models.CharField(max_length=128)
url.py
url(r"books/$",views.BookView.as_view())
view.py
""" 普通一对一字段 """ from django.shortcuts import render,HttpResponse from .models import * from rest_framework import serializers class CourseSerializer(serializers.ModelSerializer): class Meta: model = DegreeCourse # field = ["普通字段","一对一字段"] fields = ["id", "name","brief","period"] # fields = "__all__" # 所有字段 def get_teachers(self, obj): """ 针对"__all__"设置的自定义多对多字段:teachers obj_list = obj.本表多对多字段.all() """ obj_list = obj.teachers.all() return [{"id": row.id, "name": row.name} for row in obj_list]
一对多字段
""" 一对多字段 """ from django.shortcuts import render,HttpResponse from .models import * from rest_framework import serializers class BookSerializers(serializers.Serializer): # publish 是一对多的外键,如果不加source="publish.pk",则使用的是model.py中表的__str__ # source="本表的字段名.关联表的字段名" # publish: publish=serializers.CharField(source="publish.name")
多对多字段
""" 多对多字段 """ from django.shortcuts import render,HttpResponse from .models import * from rest_framework import serializers class BookSerializers(serializers.Serializer): class Meta: model = Course # 查询的表名 fields = "__all__" # 过滤的字段 depth = 2 # 跨表深度:1-10,最好不要超过3 # 针对多对多字段类型,将authors 按照下面的方式写 authors = serializers.SerializerMethodField() # 可以进行自定制显示样式: def get_xxx(self,obj):pass def get_authors(self,obj): temp=[] obj."book表'ManyToManyField'字段名".all() for author in obj.authors.all(): temp.append({"pk":author.pk,"name":author.name}) return temp # return [{"pk":author.pk,"name":author.name} for author in obj.authors.all()]
ModelSerializer
# 上面写的 BookSerializers 可以换成以下写法,更简洁 # 这里 BookSerializers 继承的是 serializers.ModelSerializer class BookSerializers(serializers.ModelSerializer): class Meta: model = Book fields = "__all__" # 当序列化类 Meta 中定义了depth 时,这个序列化类中引用字段(外键)则自动变为只读, # 所以在进行更新或者创建的操作的时候不能使用此序列化类 # depth = 1 # 以下多对多字段 authors = serializers.SerializerMethodField() def get_authors(self,obj): temp=[] for author in obj.authors.all(): temp.append({"pk":author.pk,"name":author.name}) return temp
对于POST请求:
def post(self, request, *args, **kwargs): # 得到用户添加的数据,其中request在APIView中的def dispatch中通过request = self.initialize_request(request,*args,**kwargs)进行了重新定义, # 现在使用的request = self.request._request # ① bs = BookSerializers(data=request.data, many=False) # ①
bs = BookSerializers(data=request.data, many=True) # ② if bs.is_valid(): # 对数据bs进行验证 bs.save() # ① return Response(bs.data) # ①
return HttpResponse(bs.data) # ② else: return HttpResponse(bs.errors)
# ①需要使用Response(bs.data)而不是原生的HTTPResponse;
# ②需要使用原生的HttpResponse,如果直接使用Response(bs.data)会报错,具体原因会在后面的源码分析中解释。
重写save中的create方法
""" class BookSerializers(serializers.ModelSerializer): class Meta: model=Book fields="__all__" # exclude = ['authors',] # depth=1 def create(self, validated_data): authors = validated_data.pop('authors') obj = Book.objects.create(**validated_data) obj.authors.add(*authors) return obj """
或者是用之前的方法,将代码改成以下形式:
class BookSerializers(serializers.ModelSerializer): class Meta: model = Book fields = "__all__" # 当序列化类 Meta 中定义了depth 时,这个序列化类中引用字段(外键)则自动变为只读, # 所以在进行更新或者创建的操作的时候不能使用此序列化类 # depth = 1 # 自定义authors字段的显示格式 authors = serializers.SerializerMethodField() def get_authors(self, obj): temp = [] for author in obj.authors.all(): temp.append({"pk": author.pk, "name": author.name}) return temp
单条数据的 get 和 put 请求
--- url.py url(r'^books/(?P<pk>\d+)/$', views.BookDetailViewSet.as_view(), name="book_detail"),
视图中:
class BookDetailViewSet(APIView): def get(self, request,pk, *args, **kwargs): book_list = Book.objects.filter(pk=pk) # .first # 实例化一个带有数据的 BookSerializers 对象 bs = BookSerializers(book_list) return Response(bs.data) def post(self, request, pk, *args, **kwargs): book_list = Book.objects.filter(pk=pk) bs = BookSerializers(book_list, data=request.data) if bs.is_valid(): bs.save() return Response(bs.data) else: return HttpResponse(bs.errors)
超链接 API:Hyperlinked
class BookSerializers(serializers.ModelSerializer): publish = serializers.HyperlinkedIdentityField( view_name="book_detail", # 是urls.py中的name的值 lookup_field="publish_id", # 在页面展示时的格式 lookup_url_kwarg="pk" # 匹配URL的分组命名 ) class Meta: model = Book fields = "__all__" ''' [ { "id": 1, "publish": "http://127.0.0.1:8001/books/3/", "title": "php", "price": 13, "pub_date": "2018-03-02", "authors": [2] }, { "id": 2, "publish": "http://127.0.0.1:8001/books/2/", "title": "python", "price": 24, "pub_date": "2018-04-09", "authors": [2,1] } ] '''