我曾经只使用Django,但最近开始使用DjangoRestFramework。没有DjangoRestFramework,这是我的forms.py:
class RegistrationForm(forms.Form):
username = forms.CharField(label='Username', max_length=30)
email = forms.EmailField(label='Email')
password1 = forms.CharField(label='Password', widget=forms.PasswordInput())
password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput())
def clean_password2(self):
if 'password1' in self.cleaned_data:
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 == password2:
return password2
raise forms.ValidationError('Passwords do not match.')
def clean_username(self):
username = self.cleaned_data['username']
if not re.search(r'^\w+$', username):
raise forms.ValidationError('Username can only contain alphanumeric characters and the underscore.')
try:
User.objects.get(username=username)
except ObjectDoesNotExist:
return username
raise forms.ValidationError('Username is already taken.')
我曾经将此表单传递给前端,然后当用户填写并点击提交时,我会在后端执行:
if form.is_valid():
验证表单是否有效。但是,现在我正在使用DRF和序列化程序,我在forms.py中没有任何内容。我只是在前端创建表单,如下所示:
<form ng-submit="ctrl.add()">
<label>Username</label>
<input type="text" ng-model="ctrl.user.username">
<label>Password</label>
<input type="password" ng-model="ctrl.user.password">
<label>Confirm Password</label>
<input type="password" ng-model="ctrl.user.passwordTwo">
<label>Email</label>
<input type="email" ng-model="ctrl.user.email">
<input type="submit" value="Register">
</form>
当用户点击提交时,AngularJS会将其发送到后端,如下所示:
self.add = function() {
$http.post("/users", self.user)
数据发布到的网址是&#34; / users&#34;处理它的视图是:
class user_list(APIView):
"""
Create a new user.
"""
def post(self, request):
serializer = UserSerializer(data=request.DATA)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
所以当我这样做时会进行验证:
if serializer.is_valid():
话虽如此,由于我不再使用RegistrationForm,因此不会执行额外的clean_username()和clean_password2()函数。在我没有使用DRF时,我曾经做过表格验证的正确位置在哪里?
答案 0 :(得分:2)
要在序列化程序中执行validation,我们可以定义一个函数validate_username()
来验证用户名,另一个函数validate()
验证password1
和password2
自定义字段级验证:
我们需要验证username
,我们可以为序列化程序添加函数validate_username()
。
要指定自定义字段级验证,我们需要将.validate_<field_name>
方法添加到我们的Serializer子类中。这些类似于Django表单上的.clean_<field_name>
方法。
这些方法采用单个参数,即字段值 需要验证。
您的
validate_<field_name>
方法应返回经过验证的值 或者提出serializers.ValidationError
。
对象级验证:
要进行需要访问多个字段的任何其他验证,我们需要在Serializer子类中添加一个名为.validate()
的方法。
此方法采用单个参数,该参数是字段值的字典。如果需要,它应该引发ValidationError
,或者只返回经过验证的值。
由于在clean_password2()
函数中,您也尝试访问password1
的值,我们需要通过定义validate()
函数来进行对象级验证。
最终代码:
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
...
def validate_username(self, value):
if not re.search(r'^\w+$', value):
raise serializers.ValidationError('Username can only contain alphanumeric characters and the underscore.')
if User.objects.filter(username=value):
raise serializers.ValidationError('Username is already taken.')
return value # must return validated value
def validate(self, data):
password1 = data.get('password1')
password2 = data.get('password2')
if password1 != password2:
raise serializers.ValidationError('Passwords do not match.')
return data # must return validated values