Drf之模型序列化方式总结(四)

普通drf序列化

# models.py
class Students(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    gender = models.CharField(max_length=8)
    def __str__(self):
        return 'Student: %s' % self.name
    

# 自定义序列化类:为具体的类提供序列化
# my_serializer.py
from rest_framework import serializers
class StudentSerializer(serializers.Serializer):
    # 1.如果没有source引入models的字段名,序列化字段名必须同models的字段名
    # 2.如果有source引入models的字段名,序列化字段名必须不同于models的字段名,目的是对外隐藏数据库的字段名
    id = serializers.IntegerField()
    stu_name = serializers.CharField(source='name')
    age = serializers.IntegerField()
    gender = serializers.CharField()
    

# views.py
from app import models
from app.my_serializer import StudentSerializer
class Students(APIView):
    def get(self, request, *args, **kwargs):
        stus = models.Students.objects.all()
        # 需要序列化多个对象,需要明确many=True
        stu_ser = StudentSerializer(stus, many=True)
        print(stus)
        return Response({
            'status': 0,
            'msg': 'ok',
            'results': stu_ser.data
        })
    
    
# urls.py
from app import views
urlpatterns = [
    url(r'^students/', views.Students.as_view()),
]
# 数据的传输与文件存储均是采用字符串格式

# 序列化:将对象转换成字符串的过程,进而用来传输或存储
# 反序列化:将字符串转换为对象的过程,在程序中使用

orm无关联连表操作

# models.py
class User(models.Model):
    user = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    # 1)db_constraint=False:断开外键关联,数据库操作效率提高
    # 2)避免脏数据的参数,要允许外键可为null
    # 3)on_delete=models.SET_NULL与2)协同在外键关联的数据删除掉会自动置空
    user_detail = models.OneToOneField(to='UserDetail', null=True, on_delete=models.SET_NULL, db_constraint=False)

class UserDetail(models.Model):
    phone_num = models.CharField(max_length=11)
    info = models.TextField()
    
# views.py
from app import models
def test(request):
    # models.UserDetail.objects.filter(id=1).delete()
    user = models.User.objects.first()  # type: models.User
    return HttpResponse(user.user_detail.phone_num)

函数作为模型对象序列化

# models.py
class User(models.Model):
    user = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    user_detail = models.OneToOneField(to='UserDetail', null=True, on_delete=models.SET_NULL, db_constraint=False)
    # 在model中产生的全局空间名字,都可以被序列化
    def account(self):
        return self.user + ":" + self.pwd
    
class UserDetail(models.Model):
    phone_num = models.CharField(max_length=11)
    info = models.TextField()
    

两种嵌套的序列化方式(重要)

序列化方式1
# app/objson.py (序列化层)
class UserJson(serializers.Serializer):
    # 不序列化的字段不对外提供
    # id = serializers.IntegerField()
    name = serializers.CharField(source='user')
    password = serializers.CharField(source='pwd')
    # 对指定的名字序列化(名字可以为普通对象、函数对象、类对象)
    account = serializers.CharField()
   
    # 在同一层产生数据
    # user_phone = serializers.CharField(source='user_detail.phone_num')
    # user_info = serializers.CharField(source='user_detail.info')

   
    # 产生一个序列化的字段(detail) => 可以通过get_字段名(get_detail)完成ORM的连表操作,完成序列化
    detail = serializers.SerializerMethodField()  # 本质:改字段的值由方法提供
    def get_detail(self, obj):  # 该方法的命名规范必须是 get_字段名(self, obj)
        # obj就是序列化类的对象(models.User类的对象)
        # 对象就可以利用ORM完成连表操作
        phone_num = obj.user_detail.phone_num
        info = obj.user_detail.info
        # 这里想返回什么格式都可以,字典和列表都随意
        return {'phone': phone_num, 'info': info}
序列化方式2
class UserDetailJson(serializers.Serializer):
    phone_num = serializers.CharField()
    info = serializers.CharField()

class UserJson(serializers.Serializer):
    name = serializers.CharField(source='user')
    password = serializers.CharField(source='pwd')
    account = serializers.CharField()
    
    detail = serializers.SerializerMethodField()
    def get_detail(self, obj): #obj是当前类名
        # 拿到UserDetail类的连表对象
        detail_obj = obj.user_detail  #obj.字段名
        # 完成序列化
        detail_data = UserDetailJson(detail_obj).data   #把字段名对象丢入另外的表格式化
        # 返回序列化后的数据
        return detail_data

基于Model的序列化

数据层:models.py
class Book(models.Model):
    name = models.CharField(max_length=20)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    # 多对多存在第三张表,只需要断开关联即可
    author = models.ManyToManyField(to='Author', db_constraint=False)

class Author(models.Model):
	    name = models.CharField(max_length=20)
    author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.SET_NULL, null=True, db_constraint=False)

class AuthorDetail(models.Model):
    age = models.IntegerField()
    telephone = models.BigIntegerField()
    
# objson.py

序列化层:objson.py
"""
1) 用Meta的model来绑定序列化的类
2) fields = '__all__': 序列化所有字段
3) fields = ['字段1', ..., '字段2']:指定序列化的字段
4) exclude = ['字段1', ..., '字段2']:排除序列化的字段
5) depth = 1:跨表的深度
"""
from app import models
class AuthorDetailJson(serializers.ModelSerializer):
    class Meta:
        model = models.AuthorDetail
        exclude = ['id']

class AuthorJson(serializers.ModelSerializer):
    class Meta:
        model = models.Author
        # fields = '__all__'
        exclude = ['id']

    # 如果名字是原来某字段的名字相同,会覆盖,否则就是新建:此处是覆盖
    detail = serializers.SerializerMethodField()
    def get_detail(self, obj):
        detail_data = AuthorDetailJson(obj.author_detail).data
        return detail_data

class BookJson(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        # 1.对所有字段序列化
        fields = '__all__'
        # 2.对指定字段序列化
        # fields = ['id', 'name', 'price']
        # 3.刨除指定字段序列化剩下的字段
        # exclude = ['id']
        # 4.连表操作的深度
        # depth = 1

    # 自定义深度
    # 如果名字是原来某字段的名字相同,会覆盖,否则就是新建:此处是新建
    authors = serializers.SerializerMethodField()
    def get_authors(self, obj):
        # 1.通过序列化方式
        author_list = obj.author.all()
        author_data = AuthorJson(author_list, many=True).data
        return author_data
        # 2.通过手撸ORM查询,自定义封装返回字段 *****
视图层views.py
class Books(APIView):
    def get(self, request):
        book_list = models.Book.objects.all()
        book_data = objson.BookJson(book_list, many=True).data
        return Response({
            'status': 0,
            'msg': 'ok',
            'results': book_data
        })
路由层urls.py
url(r'^books/', views.Books.as_view()),
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值