序列化验证
一般前后端分离的时候,我们都会校验前端的参数时候合法。如果我们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='您已收藏')]