Django REST framework - 序列化

Django REST framework 序列化

DRF 序列化的本質

Django ORM對象 --> JSON格式的數據 ==>此過程是序列化
相似json模塊中dumps()json

JSON格式的數據 --> Django ORM的數據 ==>此過程是反序列化
相似json模塊中loadsapp

DRF中序列化工具

from rest_framework.serializers import Serializer
from rest_framework.serializers import MoselSerializer

類比Django中的form組件
Django form --> HTML表單
HTML表單 -->ORM數據工具

安裝DRF

pip install djangorestframework

添加rest_framework應用

註冊app(非必須的)

INSTALLED_APPS = [
...
'rest_framework',

]post

定義Serializer

class BookInfoSerializer(serializers.Serializer):
    pass
or
class BookInfoSerializer(serializers.MoselSerializer):
    pass

使用DRF序列化器 示例

表結構

class Article(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=64)
    create_time = models.DateField(auto_now=True)
    type = models.SmallIntegerField(
        choices=((1, '原創'), (2, '轉載')),
        default=1
    )
    source = models.ForeignKey(to='Source', on_delete=models.CASCADE)
    tag = models.ManyToManyField(to='Tag')


class Source(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32, unique=True, error_messages={"unique": '校區名稱不能重複'})


class Tag(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)


class Comment(models.Model):
    content = models.CharField(max_length=255)
article = models.ForeignKey(to='Article', on_delete=models.CASCADE)

一. 單表的GET和POST

路由

url(r'source/', views.SourceView.as_view()),

序列化類

class SourceSerializer(serializers.ModelSerializer):

    def validate_name(self, value):
        if '草' in value:
            raise ValidationError('不符合社會主義核心價值觀')
        return value

    class Meta:
        model = models.Source
        fields = "__all__"

視圖

class SourceView(APIView):

    def get(self, request, *args, **kwargs):
        res = {"code": 0}
        all_source = models.Source.objects.all()
        ser_obj = SourceSerializer(all_source, many=True)
        res["data"] = ser_obj.data
        return Response(res)

    def post(self, request, *args, **kwargs):
        res = {"code": 0}
        ser_obj = SourceSerializer(data=request.data)
        if ser_obj.is_valid():
            # 數據沒問題
            ser_obj.save()
            return Response(res)
        else:
            res["code"] = 1
            res["error"] = ser_obj.errors
            return Response(res)

二. 外鍵的GET和POST

路由

url(r'comment/', views.Comment.as_view()),

序列化

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Comment
        fields = "__all__"
        extra_kwargs = {
            "content": {"error_messages": {"required": "評論內容不能爲空"}},
            "article": {"error_messages": {"required": "文章不能爲空"}}
        }

視圖

class Comment(APIView):
    def get(self, request, *args, **kwargs):
        res = {"code": 0}
        all_data = models.Comment.objects.all()
        ser_obj = CommentSerializer(all_data, many=True)
        res["data"] = ser_obj.data
        return Response(res)

    def post(self, request, *args, **kwargs):
        res = {"code": 0}
        ser_obj = CommentSerializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
        else:
            res["code"] = 1
            res["error"] = ser_obj.errors
        return Response(res)

多對多的GET和POST

路由

url(r'article/', views.ArticleList.as_view()),

序列化

class TagSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Tag
        fields = "__all__"


class ArticleSerializer(serializers.ModelSerializer):
    type = serializers.CharField(source="get_type_display")
    tag = TagSerializer(many=True)

    class Meta:
        model = models.Article
        fields = ["id", "title", "type", "source", "tag"]


class ArticleWriteSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Article
        fields = "__all__"
        extra_kwargs = {
            "tag": {
                "error_messages": {
                    "does_not_exist": '"{pk_value}"對應的tag對象不存在。'
                }
            }
        }

三. 視圖

class ArticleList(APIView):
    def get(self, request, *args, **kwargs):
        res = {"code": 0}
        article_list = models.Article.objects.all()
        ser_obj = ArticleSerializer(article_list, many=True)
        res["data"] = ser_obj.data
        return Response(res)

    def post(self, request, *args, **kwargs):
        res = {"code": 0}
        ser_obj = ArticleWriteSerializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
        else:
            res["code"] = 1
            res["error"] = ser_obj.errors
        return Response(res)

四. 超連接的序列化

路由

urlpatterns = [
    url(r'articlelinked/', views.ArticleLinked.as_view()),,
    url(r'source/(?P<pk>\d+)', views.SourceDetailView.as_view(), name='source-detail'),
]

序列化

class ArticleHyperlinkedSerializer(serializers.HyperlinkedModelSerializer):
    source = serializers.HyperlinkedIdentityField(view_name='source-detail', lookup_field='source_id', lookup_url_kwarg='pk')

    class Meta:
        model = models.Article
        fields = ["id", "type", "title", "source"]
        depth = 1

視圖

class ArticleLinked(APIView):
    def get(self, request, *args, **kwargs):
        res = {"code": 0}
        article_list = models.Article.objects.all()
        ser_obj = ArticleHyperlinkedSerializer(article_list, many=True, context={'request': request})
        res["data"] = ser_obj.data
        return Response(res)

序列化補充 跨表的序列化

方法一

class ModelCourseCategoryView(serializers.ModelSerializer):
    # price = serializers.SerializerMethodField()
    # learn_num = serializers.SerializerMethodField()
    

    # def get_price(self, obj):
    #     price_obj = obj.price_policy.all().filter(valid_period=723).first()
    #     return price_obj.price
    #
    # def get_learn_num(self, obj):
    #     return obj.order_details.count()

方法二

source 支持被序列化對象的點操做ui

learn_num = serializers.IntegerField(source='order_details.count')
course_detail_id = serializers.IntegerField(source='coursedetail.id')

方法三

to_representation終級方法url

# 修改序列化結果的終極方法
def to_representation(self, instance):
    # 調用父類的同名方法把序列化的結果拿到
    data = super().to_representation(instance)
    # 針對序列化的結果作一些自定製操做
    # 判斷當前這個課程是否有永久有效的價格
    price_obj = instance.price_policy.all().filter(valid_period=999).first()
    if price_obj:
        # 有永久有效的價格
        data['has_price'] = True
        data['price'] = price_obj.price
        else:
            # 沒有永久有效的價格策略
            data['has_price'] = False
            return data
相關文章
相關標籤/搜索