为什么 DRF 的序列化器不验证 PositiveSmallIntegerField?

epa*_*alm 4 python django validation django-rest-framework

使用 Django 1.11 和 Django Rest Framework 3.7,我有一个 Person 模型

class Person(models.Model):

    name = models.CharField(max_length=100)
    email = models.EmailField()
    age = models.PositiveSmallIntegerField()
Run Code Online (Sandbox Code Playgroud)

使用 PersonSerializer

class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = ('id', 'name', 'age', 'email')
Run Code Online (Sandbox Code Playgroud)

和一个 ListCreate 视图

class PersonList(generics.ListCreateAPIView):
    queryset = Person.objects.all()
    serializer_class = PersonSerializer
Run Code Online (Sandbox Code Playgroud)

使用 HTTPie,我可以创建一个像这样的 Person:

$ http POST http://127.0.0.1:8000/api/people/ name=Alice age=26 email=alice@example.com
HTTP/1.0 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 60
Content-Type: application/json
Date: Sun, 10 Dec 2017 15:00:28 GMT
Server: WSGIServer/0.1 Python/2.7.11
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
    "age": 26,
    "email": "alice@example.com",
    "id": 1,
    "name": "Alice"
}
Run Code Online (Sandbox Code Playgroud)

当我创建一个电子邮件地址错误的人员时,出现错误:

$ http POST http://127.0.0.1:8000/api/people/ name=Bob age=33 email=oops
HTTP/1.0 400 Bad Request
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 42
Content-Type: application/json
Date: Sun, 10 Dec 2017 15:01:08 GMT
Server: WSGIServer/0.1 Python/2.7.11
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
    "email": [
        "Enter a valid email address."
    ]
}
Run Code Online (Sandbox Code Playgroud)

DRF 知道它是一个 EmailField 并自动应用验证,到目前为止一切顺利。

但是,当我创建一个年龄不好(负数)的人时,我没有收到错误:

$ http POST http://127.0.0.1:8000/api/people/ name=Charlie age=-10 email=charlie@example
.com
HTTP/1.0 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 65
Content-Type: application/json
Date: Sun, 10 Dec 2017 15:03:25 GMT
Server: WSGIServer/0.1 Python/2.7.11
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
    "age": -10,
    "email": "charlie@example.com",
    "id": 3,
    "name": "Charlie"
}
Run Code Online (Sandbox Code Playgroud)

现在我的数据库已被不良数据污染。我可以毫无问题地验证我的输入,但是

  • DRF 正确验证了电子邮件字段,让我相信它将根据模型中的字段类型验证输入。
  • 如果我从 html 表单发布,Django 的 ModelForm 将会验证电子邮件和年龄字段。
  • 如果我从标准 Django Admin 创建了一个 Person,它也会验证电子邮件和年龄字段。

基于这些事实,我的问题是:

(A) 为什么 DRF 的序列化器验证 EmailField,而不验证 PositiveSmallIntegerField?

(B) 我应该在哪里验证“年龄”字段以确保其为正数?模型?串行器?看法?

man*_*ica 8

将验证器添加到模型中的字段:

from django.core.validators import MinValueValidator
from django.core.validators import MaxValueValidator

class Person(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()
    age = models.PositiveSmallIntegerField(validators=[MinValueValidator(0), MaxValueValidator(120)])
Run Code Online (Sandbox Code Playgroud)


Saj*_*ier 5

在DRF中,IntegerField对应于PositiveIntegerField,因此您可以对其设置最大值和最小值限制。

例如:

class PersonSerializer(serializers.ModelSerializer):
    age = serializers.IntegerField(max_value=100, min_value=1)
    class Meta:
        model = Person
        fields = ('id', 'name', 'age', 'email')
Run Code Online (Sandbox Code Playgroud)

  • 这就是问题B的答案,谢谢。但我仍然不满意,因为我不知道 DRF 何时基于模型进行验证,何时不进行验证。 (2认同)