我正在使用DRF编写密文加密/解密API,我遇到了一个奇怪的问题。我已经定义了我的一个模型:
class Key(models.Model):
owner = models.ForeignKey(User, related_name='keys')
content = models.CharField(max_length=50)
name = models.CharField(max_length=100, blank=True, default='')
created = models.DateTimeField(auto_now_add=True)
alphabet = models.TextField(default=string.ascii_lowercase+string.digits)
此模型的序列化程序(我省略了一些与问题无关的方法):
class KeySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Key
fields = ('url', 'id', 'alphabet', 'content', 'name')
def validate(self, attrs):
alphabet = attrs.get('alphabet')
if alphabet and len(alphabet) > len(set(alphabet)):
raise ValidationError({'alphabet': 'This field should not contain repeated characters.'})
alphabet = alphabet or Key._meta.get_field('alphabet').default
if not all(map(lambda x: x in alphabet, attrs.get('content'))):
raise ValidationError({'content': 'Invalid characters were provided.'})
data = dict()
if 'name' in attrs:
data['name'] = attrs['name']
if 'alphabet' in attrs:
data['alphabet'] = attrs['alphabet']
if 'content' in attrs:
data['content'] = attrs['content']
return data
最后,发布和列出Key
的视图:
class KeyList(generics.ListCreateAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = KeySerializer
def get_queryset(self):
return Key.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
我遇到的问题是,当我尝试通过浏览器发布密钥时,使用alphabet
属性的空字符串,如下所示:
{
"alphabet": ""
"content": "foobar"
}
我收到以下回复:
{
"alphabet": ['This field may not be blank.']
}
当然,这是理想的行为。 然而,当我从测试用例或shell发布相同的东西时,我得到了这个:
$ python manage.py shell
Python 2.7.11 (default, Dec 5 2015, 14:44:53)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.1.76)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.test import Client
>>> from django.core.urlresolvers import reverse
>>>
>>> client = Client()
>>> client.login(username='password', password='username')
True
>>>
>>> response = client.post(reverse('key-list'), data={'alphabet': '', 'content':'guacamole'})
>>> response.data
{'name': u'', 'url': u'http://testserver/myapp/keys/8/', 'alphabet': u'abcdefghijklmnopqrstuvwxyz0123456789', 'content': u'guacamole', 'id': 1}
也就是说,当我从测试用例或shell发布时,不会引发验证错误。为什么会这样?
我还应该注意,当我尝试为content
属性发布空字符串时,不会发生同样的问题。这让我怀疑它与alphabet
是TextField
有关,但我不知道如何解释原因。
答案 0 :(得分:0)
字母表字段具有默认值,因此当您直接通过模型保存时,模型会接受空白并将其替换为默认值。当您使用shell时,触发模型验证。
使用浏览器,您会触发另一个需要字段的验证,然后失败。
错误是这样的:
alphabet = alphabet or Key._meta.get_field('alphabet').default
它没有像模型那样返回正确的默认值。