为了账号安全,请及时绑定邮箱和手机立即绑定

Django:如何在基于类和基于函数的自定义验证器之间做出决定?

Django:如何在基于类和基于函数的自定义验证器之间做出决定?

米琪卡哇伊 2023-10-31 21:46:11
这是一个初学者的问题。我最初是这样声明该字段的:from django.db import modelsfrom django.core.validators import FileExtensionValidatordef user_directory_path(instance, filename):    """    Code to return the path    """class Project(models.Model):    """    """    # ...Some model fields...    # Right now I'm only validating and testing with .mp4 files.    video_file = models.FileField(        upload_to=user_directory_path,        validators=[FileExtensionValidator(allowed_extensions=['mp4'])]    )但我在几个地方读到,最好使用它libmagic来检查文件的幻数并确保其内容与扩展名和 MIME 类型匹配。我对此很陌生,所以我可能会弄错一些东西。我按照验证器参考编写了一个使用magic. 该文档还讨论了“带有方法的类”,这里__cal__()获得最多支持的答案使用基于类的验证器。文档说这可以“对于更复杂或可配置的验证器”来完成,但我不明白具体的例子是什么,以及我的基于函数的验证器是否足以满足我想要做的事情。我想是的,但我没有经验来确定。这就是我所拥有的。models.pyfrom django.db import modelsfrom .validators import validate_media_filedef user_directory_path(instance, filename):    """    Code to return the path    """class Project(models.Model):    """    """    # ...Some model fields...    # Right now I'm only validating and testing with .mp4 files.    video_file = models.FileField(        upload_to=user_directory_path,        validators=[validate_media_file]    )迁移工作与此相关。我还使用扩展名为 .mp4 的纯文本文件进行了测试,然后使用不同的文件(和扩展名)对其进行了测试,并且它可以工作。但是,我想知道使用它而不是基于类的验证器是否会丢失一些东西,而且,正如标题所说,我应该何时使用它,因为我可能会遇到另一种情况,在这种情况下我会需要知道它。我知道我没有包含 MIME 类型;我可以稍后再做。magic.from_buffer()作为另一个问题,当输出与扩展名和/或 MIME 类型不匹配时,适当的错误消息是什么?我想到了“文件已损坏”的说法,但我不确定。实际上,这是直接基于幻数的输出吗?
查看完整描述

1 回答

?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

何时使用基于类的验证器?

在您的示例中,基于函数的验证器就足够了。如果您需要 OOP、类和对象的优点,那么您应该切换到基于类的验证器。想象一下以下非常虚构的源代码:


class StartsWithValidator():

    def __init__(self, starts_with):

        self.starts_with = starts_with


    def __call__(self, value):

        if not str(value).startswith(self.starts_with):

            raise ValidationError(

                'Your string does not start with: {}!'.format(self.starts_with),

                params={'value': value}

            )


my_validator = StartsWithValidator('123')

test_string = '123OneTwoThree'

my_validator(test_string) # Will it pass the validator?

您可以在这里看到不同的品质:


通过基于类的验证器,您可以使用对象。对象共享相同的功能但具有不同的内部状态。您现在可以设置一个验证器,它检查字符串是否以“abc”、“123”开头,而无需编写新代码

starts_with_abc = StartsWithValidator('abc')

starts_with_123 = StartsWithValidator('123')

starts_with_whatever = StartsWithValidator('whatever')

您可以使用继承。想象一下,您想要在其他功能中重用starts-with-validation,您只需从“StartsWithValidator”类继承即可。

class StartsWithABCValidator(StartsWithValidator):

    def __init__(self):

        super().__init__('ABC')


    def __call__(self, value):

        super().__call__(value)

如果你的验证器做了很多复杂的事情,一个简单的函数可能会导致可读性差的代码。如果您使用类,您就可以封装您的功能并将其分组在一起。


查看完整回答
反对 回复 2023-10-31
  • 1 回答
  • 0 关注
  • 58 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信