Django ModelForm:如何很少执行昂贵的字段验证?

时间:2016-04-05 18:50:41

标签: django validation django-models django-forms

我有一个有十几个字段的模型。 它的实例是通过一个包含大约十几个字段的表单创建的。 其中一个字段是我需要检查实际可访问性的URL。 该检查需要登录并需要相当长的时间(约4秒), 所以我想尽可能少地执行它 - 但也是 早在用户期望的时候,即在输入URL之后。

简而言之,我想在表单验证时验证网址, 除非我在之前验证了相同的网址(在 先前的请求)。

我想知道在哪里放这个逻辑。 我的代码使用vanilla.CreationView基于类的视图。

from django.db import models
import vanilla

class MyModel(models.model):
    url = models.URLField()  # a very remote URL
    # and many others

class CreateView(vanilla.CreateView):
    model = MyModel
    template_name = "create.html"

我首先尝试直接在模型中进行检查, 以某种方式使用has_changed()

我花了很长时间才意识到这一点 不能工作(我还是Django的新手): 表单无法知道提交的内容 之前的 POST请求,因为没有合适的状态 可用:

  • 模型实例尚不存在(这是创建视图!)。
  • 该模型即使在UpdateView中也无济于事, 因为用户可能会多次更改该值 两个save()调用之间,而表单没有 验证

似乎有两种可能性:

  • 将持久状态存储在单独的ValidationStatus模型中。 这听起来很麻烦,就像一个可怕的过度杀伤。
  • 让浏览器通过手段发回以前的值 一个隐藏的领域。 听起来对我来说更明智。

两个问题:

  • 上述考虑是否正确?
  • 添加此类隐藏字段的代码最小化方法是什么 到实际的形式和管理验证工作流程? 我想保持提供的可爱的自动化支持 尽可能通过Django和vanilla的观点。

1 个答案:

答案 0 :(得分:0)

缓存!

koniiiik的评论是正确的:这是caching的完美用例,因为就我而言,该URL的可访问性 是一个全球财产; 它不依赖于用户,因此不依赖于会话, 并且与该特定表单或模型实例无关。

我现在已经实现了一个简单的validator function附加到 url模型字段如下:

    def validate_url_accessibility(url):
        cache_key = "%s is accessible" % url
        if django.core.cache.cache.get(cache_key):
            return  # alright: access has been validated before
        if not accessible(url):
            raise ValidationException("...")
        django.core.cache.cache.set(cache_key, True)

像魅力一样。