使用 Django Rest Framework 3、基于函数的视图和 ModelSerializer(更具体地说是 HyperlinkedModelSerializer)。
当用户从客户端提交表单时,我有一个视图,该视图获取请求数据,使用它调用外部 API,然后使用来自外部 API 的数据填充模型序列化程序的数据。我相信我这部分工作正常,从我读到的内容来看,你应该使用上下文和validate()
在我的模型序列化程序中,到目前为止,我只有一个覆盖函数:
from django.core.validators import URLValidator
def validate(self, data):
if 'foo_url' in self.context:
data['foo_url'] = self.context['foo_url']
URLValidator(data['foo_url'])
if 'bar_url' in self.context:
data['bar_url'] = self.context['bar_url']
URLValidator(data['bar_url'])
return super(SomeSerializer, self).validate(data)
以防万一,相关的视图代码如下所示:
context = {'request': request}
...
context['foo_url'] = foo_url
context['bar_url'] = bar_url
s = SomeSerializer(data=request.data, context=context)
if s.is_valid():
s.save(user=request.user)
return Response(s.data, status=status.HTTP_201_CREATED)
现在假设我的想法是正确的(我的模型确实从相应的上下文数据中填充了它的foo_url
和bar_url
字段),我感到困惑的是验证是如何不起作用的。 如果我给它错误的数据,模型序列化程序不会拒绝它。
我假设在validate()
中,通过将上下文数据添加到数据中,当调用is_valid()
时,将检查数据的有效性。 也许情况并非如此,尤其是当我打印出s
时(在使用序列化程序之后但在调用is_valid()
之前),没有迹象表明请求对象的data
已填充了来自validate()
的上下文数据(我不知道是否应该如此)。
所以我尝试直接在validate()
方法中调用 URLValidators,但似乎仍然不起作用。 尽管给了它无效的数据,如"asdf"或空的python字典({}),但没有错误。 我的测试断言表明该字段确实包含无效数据,例如"{}"。
正确的方法是什么?
你没有调用验证器。
通过这样做URLValidator(data['bar_url'])
您实际上是在构建一个具有自定义方案的 url 验证器(请参阅文档),仅此而已。正确的代码应该是:
URLValidator()(data['bar_url'])
在其中构建默认 url 验证程序,然后验证值。
但无论如何我不会使用这种方法,而是直接添加额外的数据(不使用上下文),并让 DRF 通过声明正确的字段进行验证:
# Somewhere in your view
request.data['bar_url'] = 'some_url'
# In serializer:
class MySerializer(serializers.ModelSerializer):
bar_url = serializers.URLField()
class Meta:
fields = ('bar_url', ...)
回答您的评论
我也不明白这也是如何通过 Django 的模型验证
看到这个答案: 为什么 django 的 model.save() 不调用 full_clean()?
默认情况下,Django 不会自动调用.full_clean
方法,因此您可以保存具有无效值的模型实例(除非约束在数据库级别)。