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]
  }
]
'''

 

posted @ 2018-04-12 16:35  焦国峰的随笔日记  阅读(206)  评论(0编辑  收藏  举报
// ############################### // ##############################