数据校验&序列化放到同一个类。
    前面示例均属于单一功能(要么校验,要么序列化),其实当我们编写一个序列化类既可以做数据校验,也可以做序列化。

    • read_only 只用于序列化,不用于校验。
    • wrire_only 只用于校验,不用于序列化。

    image.png
    序列化
    image.png
    数据校验
    image.png

    1. # models.py
    2. from django.db import models
    3. class Role(models.Model):
    4. """ 角色表 """
    5. title = models.CharField(verbose_name="名称", max_length=32)
    6. class Department(models.Model):
    7. """ 部门表 """
    8. title = models.CharField(verbose_name="名称", max_length=32)
    9. class UserInfo(models.Model):
    10. """ 用户表 """
    11. level_choices = ((1, "普通会员"), (2, "VIP"), (3, "SVIP"),)
    12. level = models.IntegerField(verbose_name="级别", choices=level_choices, default=1)
    13. username = models.CharField(verbose_name="用户名", max_length=32)
    14. password = models.CharField(verbose_name="密码", max_length=64)
    15. age = models.IntegerField(verbose_name="年龄", default=0)
    16. email = models.CharField(verbose_name="邮箱", max_length=64, null=True, blank=True)
    17. token = models.CharField(verbose_name="TOKEN", max_length=64, null=True, blank=True)
    18. depart = models.ForeignKey(verbose_name="部门", to="Department", on_delete=models.CASCADE, null=True, blank=True)
    19. roles = models.ManyToManyField(verbose_name="角色", to="Role")
    1. # urls.py
    2. from django.urls import path, re_path, include
    3. from app01 import views
    4. urlpatterns = [
    5. path('api/users/', views.UserView.as_view()),
    6. ]
    1. # views.py
    2. from django.core.validators import EmailValidator
    3. from rest_framework.views import APIView
    4. from rest_framework.response import Response
    5. from rest_framework import serializers
    6. from app01 import models
    7. class DepartModelSerializer(serializers.ModelSerializer):
    8. class Meta:
    9. model = models.Department
    10. fields = ['id', "title"]
    11. extra_kwargs = {
    12. "id": {"read_only": False}, # 数据验证
    13. "title": {"read_only": True} # 序列化
    14. }
    15. class RoleModelSerializer(serializers.ModelSerializer):
    16. class Meta:
    17. model = models.Role
    18. fields = ['id', "title"]
    19. extra_kwargs = {
    20. "id": {"read_only": False}, # 数据验证
    21. "title": {"read_only": True} # 序列化
    22. }
    23. class UserModelSerializer(serializers.ModelSerializer):
    24. level_text = serializers.CharField(source="get_level_display", read_only=True)
    25. # Serializer嵌套,不是read_only,一定要自定义create和update,自定义新增和更新的逻辑。
    26. depart = DepartModelSerializer(many=False)
    27. roles = RoleModelSerializer(many=True)
    28. extra = serializers.SerializerMethodField(read_only=True)
    29. email2 = serializers.EmailField(write_only=True)
    30. # 数据校验:username、email、email2、部门、角色信息
    31. class Meta:
    32. model = models.UserInfo
    33. fields = [
    34. "username", "age", "email", "level_text", "depart", "roles", "extra", "email2"
    35. ]
    36. extra_kwargs = {
    37. "age": {"read_only": True},
    38. "email": {"validators": [EmailValidator, ]},
    39. }
    40. def get_extra(self, obj):
    41. return 666
    42. def validate_username(self, value):
    43. return value
    44. # 新增加数据时
    45. def create(self, validated_data):
    46. """ 如果有嵌套的Serializer,在进行数据校验时,只有两种选择:
    47. 1. 将嵌套的序列化设置成 read_only
    48. 2. 自定义create和update方法,自定义新建和更新的逻辑
    49. 注意:用户端提交数据的格式。
    50. """
    51. depart_id = validated_data.pop('depart')['id']
    52. role_id_list = [ele['id'] for ele in validated_data.pop('roles')]
    53. # 新增用户表
    54. validated_data['depart_id'] = depart_id
    55. user_object = models.UserInfo.objects.create(**validated_data)
    56. # 在用户表和角色表的关联表中添加对应关系
    57. user_object.roles.add(*role_id_list)
    58. return user_object
    59. class UserView(APIView):
    60. """ 用户管理 """
    61. def get(self, request):
    62. """ 添加用户 """
    63. queryset = models.UserInfo.objects.all()
    64. ser = UserModelSerializer(instance=queryset, many=True)
    65. return Response({"code": 0, 'data': ser.data})
    66. def post(self, request):
    67. """ 添加用户 """
    68. ser = UserModelSerializer(data=request.data)
    69. if not ser.is_valid():
    70. return Response({'code': 1006, 'data': ser.errors})
    71. ser.validated_data.pop('email2')
    72. instance = ser.save(age=18, password="123", depart_id=1)
    73. # 新增之后的一个对象(内部调用UserModelSerializer进行序列化)
    74. print(instance)
    75. # ser = UserModelSerializer(instance=instance, many=False)
    76. # ser.data
    77. return Response({'code': 0, 'data': ser.data})