【问题标题】:Django - checking for model field formatDjango - 检查模型字段格式
【发布时间】:2013-02-25 17:40:29
【问题描述】:


我在 Django 中定义了一个简单的模型:

class Student(models.Model):
    s_name = models.CharField(max_length=32)
    s_gpa = models.FloatField(min=0.0, max=5.0, default=5.0)
    s_year = models.IntegerField(min=1, max=10, default=1)
    s_registered = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return self.username

    def modify(self, **kwargs):
        if valid(self, kwargs):
            for k,v in kwargs.iteritems():
                setattr(self, k, v)
            self.save()

def valid(s, kwargs):
    # For all k,v pairs in kwargs
    # (1) Checks if k is one of the attributes of s. Returns False if fails.
    # (2) Checks if v fits the format defined for attribute k of s.
    # Returns False if fails.
    # Returns True if reaches this point.

我正在编写函数 valid,我想执行 cmets 中详述的命令。
对于 (1),我使用

if k not in s.__dict__: return False

我需要一些关于 (2) 的帮助。
也就是说,如何检查值是否符合为属性(Django 模型字段)定义的格式?

例如:valid(s_name=True) 和 valid(s_name=33*'a') 都应该返回 False。

注意:我正在尝试在不使用表单的情况下解决此验证问题。

【问题讨论】:

  • 顺便说一句 - 使用 'self' 作为方法的第一个参数是常见的做法 - python.org/dev/peps/pep-0008/#function-and-method-arguments
  • 感谢 Aidan 指出这一点。实际上,我的意图是让 valid() 独立于 Student。我从一个单独的 utils 模块导入它。我把它留在学生的定义中是一个意外。再次感谢您引起我的注意。
  • 我仍然不相信这是要走的路。看看我更新的答案,也许再看看模型验证文档。

标签: python django django-models python-2.7


【解决方案1】:

您的validmodify 函数都应该替换为clean 方法。

查看model validation上的文档

更新 1

您可以完全放弃有效方法,而只需调用self.clean_feilds()。这将验证字段 -

def modify(self, **kwargs):
    try:
        self.clean_fields()
        for k,v in kwargs.iteritems():
            setattr(self, k, v)
        self.save()
    except:
        pass

更新 2

从您的 cmets 看来,您根本不需要自己调用任何验证。只需调用save,然后在您的更改无效时捕获ValidationError

def modify(self, **kwargs):
    try:
        for k,v in kwargs.iteritems():
            setattr(self, k, v)
        self.save()
    except ValidationError:
        #... do something?

值得注意的是,许多 python 程序员更喜欢 try / except 模式而不是 if valid / then。它被称为“请求宽恕而不是许可”原则(除其他外,它提供了针对竞争条件的保护 - 在这种情况下可能不相关)

【讨论】:

  • 不错的答案。它看起来最简洁。上面,我试图提供一种测试单个字段的方法,这听起来不像问题实际要求的功能。
  • 我想我明白你在说什么。因此,当我们调用 self.clean_fields() 时,它会获取 Student 实例 (self),验证其字段并在某些内容未验证时引发一些异常。但是,在您的示例中,我们不应该首先使用 setattr 调用 kwargs 上的循环,然后在该人的新外观上调用 clean_fields 吗?并且只有在清理没有引发异常时才调用 self.save() ..
  • 我认为(根据您的代码)您想要验证字段,然后设置您的属性。如果需要,也许您可​​以在添加属性后(但在保存之前)使用 self.full_clean 再次验证。
  • 我基本上会使用这个函数来修改在我调用它们之前创建和保存的实例。我想实例在上次保存时已经过验证(并通过了验证),所以这次我只需要检查它是否仍然可以通过更改进行验证。
  • 因此,只需保存对象并捕获在您的更改无效时引发的 ValidationError - 您不需要调用 valid / clean / 其他任何东西 - 只需调用 save。
【解决方案2】:

根据需要使用sself

def valid(self, kwargs):
    for k, v in kwargs:
        old_v = self.__dict__[k]
        self.__dict__[k] = v
        try:
            self.save()
            self.__dict__[k] = old_v
            self.save()
        except:
            return False

        return True

执行测试的方法可能比实际的“self.save()”失败更直接,但这是一个很好的起点。

或者:

field_list = ['s_name', 's_gpa', 's_year', 's_registered']
def valid(self, kwargs):
    for k, v in kwargs:
        exclude_list = [f for f in field_list if f != k]
        try:
            self.clean_fields(exclude=exclude_list)
        except ValidationError:
            return False

        return True

使用列表解析,删除 exclude_list 行并将 self.clean_fields 行更改为:

self.clean_fields(exclude=[f for f in field_list if f != k])

【讨论】:

    猜你喜欢
    • 2015-03-24
    • 2015-08-11
    • 2015-06-20
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多