1. 主页
  2. DRF实战教程
  3. DRF实战之序列化验证

DRF实战之序列化验证

序列化验证

一般前后端分离的时候,我们都会校验前端的参数时候合法。如果我们ModelSerializer话,因为它本身已经帮我们写好create方法,所以我们基本不需要再写验证。但是一些特殊的我们就需要重写或者自己写验证方法。

模型类

from django.db import models


# Create your models here.
class User(models.Model):
    genders = (
        (1, '男'), (2, "女")
    )
    name = models.CharField(max_length=10, verbose_name='名字')
    phone = models.CharField(max_length=11, verbose_name='手机号')
    gender = models.IntegerField(choices=genders, verbose_name='性别')

视图

@csrf_exempt
def user_list(request):
    if request.method == 'GET':
        users = User.objects.all()
        serializer = UserSerializer(users, many=True, context={'request': request})
        return JSONResponse(serializer.data)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = UserSerializer(data=data, context={'request': request})
        if serializer.is_valid():
            serializer.save()
            return JSONResponse(serializer.data, status=201)
        return JSONResponse(serializer.errors, status=400)


@csrf_exempt
def user_detail(request, id):
    try:
        user = User.objects.get(id=id)
    except User.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == 'GET':
        serializer = UserSerializer(user, context={'request': request})
        return JSONResponse(serializer.data)

    elif request.method == 'PUT':
        data = JSONParser().parse(request)
        serializer = UserSerializer(user, data=data, context={'request': request})
        if serializer.is_valid():
            serializer.save()
            return JSONResponse(serializer.data)
        return JSONResponse(serializer.errors, status=400)

    elif request.method == 'DELETE':
        user.delete()
        return HttpResponse(status=204)

路由

from django.contrib import admin
from django.urls import path, include
from . import views

urlpatterns = [
    path('users/', views.user_list, name='user_list'),  # 获取或创建
    path('users/<int:id>/', views.user_detail, name='user-detail'),  # 查找、更新、删除
]

序列化

class ChoiceDisplayField(serializers.Field):
    """Custom ChoiceField serializer field."""

    def __init__(self, choices, **kwargs):
        """init."""
        self._choices = OrderedDict(choices)
        super(ChoiceDisplayField, self).__init__(**kwargs)

    # 返回可读性良好的字符串而不是 1,-1 这样的数字
    def to_representation(self, obj):
        """Used while retrieving value for the field."""
        return self._choices[obj]

    def to_internal_value(self, data):
        """Used while storing value for the field."""
        for i in self._choices:
            # 这样无论用户POST上来但是CHOICES的 Key 还是Value 都能被接受
            if i == data or self._choices[i] == data:
                return i
        raise serializers.ValidationError("Acceptable values are {0}.".format(list(self._choices.values())))
from rest_framework import serializers
from .models import User
import re


class UserSerializer(serializers.ModelSerializer):
    GENDERS = (
        (1, '男'), (2, "女")
    )
    phone = serializers.CharField(max_length=11, required=True)
    pwd1 = serializers.CharField(write_only=True)

    gender = ChoiceDisplayField(choices=GENDERS)


    class Meta:
        model = User
        fields = '__all__'

    # 这两个方法一定要有返回值

    def validate_phone(self, phone):
        if not re.match(r'1[3456789]\d{9}', phone):
            raise serializers.ValidationError('手机号不合法')

        if User.objects.filter(phone=phone).all():
            raise serializers.ValidationError('手机号已被注册')
        return phone

    # 两次密码是否一样
    def validate(self, attrs):
        print(attrs)
        if attrs['pwd'] != attrs['pwd1']:
            raise serializers.ValidationError('两次密码不一样')
        attrs.pop("pwd1")
        return attrs

可以看到,我们自己重写了phone属性,并且自己写了validate_phone验证方法。

Validators

  • UniqueValidator:对象是唯一
username = serializers.CharField(required=True, allow_blank=False, label="用户名", max_length=16, min_length=6,validators=[UniqueValidator(queryset=User.objects.all(), message="用户已经存在")],error_messages={
                                         "blank": "用户名不允许为空",
                                         "required": "请输入用户名",
                                         "max_length": "用户名长度最长为16位",
                                         "min_length": "用户名长度至少为6位"
                                     })
  • UniqueTogetherValidator:联合唯一
class UserFav(models.Model):
    user = models.ForeignKey(User,verbose_name="用户",on_delete=False)
    goods = models.ForeignKey(Goods,verbose_name="商品",on_delete=False)
    add_time = models.DateTimeField(default=datetime.now,verbose_name="用户收藏")

    class Meta:
        verbose_name = "用户收藏"
        verbose_name_plural=verbose_name
        unique_together = (('user','goods'),)
        
class UserFavSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = UserFav
        fields = ('id','user', 'goods')
        validators = [UniqueTogetherValidator(queryset=UserFav.objects.all(),fields=('user','goods'),message='您已收藏')]

我们要如何帮助您?

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注