【问题标题】:Django save() overriding, best practice: on model, form or view?Django save() 覆盖,最佳实践:在模型、表单或视图上?
【发布时间】:2018-02-01 17:02:13
【问题描述】:

我已经成功地通过覆盖save() 函数来散列我的自定义用户模型的密码,如下所示:

def save(self, commit = True): 
    user = super(RegisterForm, self).save(commit = False)
    user.set_password(self.cleaned_data["password1"])
    if commit:
        user.save()
    return user

但是我已经在我的注册表单定义中放置了这个覆盖,我突然想到我也可以在 User 模型定义中或在我的 register() 视图中执行此操作。

是否有“正确”的位置来覆盖这些函数,例如 clean()save()?有什么实际区别吗?

ps:我对使用 Django 的默认密码更改和注册视图或表单不感兴趣。

【问题讨论】:

    标签: django django-models django-forms django-views


    【解决方案1】:

    在挖掘源代码后,我发现 ModelForm 的 save() 方法正在调用模型的(模型实例)save() 方法。检查它here.

    现在很明显,第一个 ModelForm 的 save() 被调用并在其中(取决于提交值)Model 的 save() 被调用。

    另外值得注意的是,在代码中:

    def save(self, commit = True): 
        user = super(RegisterForm, self).save(commit = False)
        user.set_password(self.cleaned_data["password1"])
        #When you're hashing and setting the password to the user variable,
        #this user variable is a Model Object but is not saved in the database yet. 
        if commit:
            user.save()
            #Now in the above line you're ultimately calling the save method of Model instance.
        return user
    

    所以问题归结为你。

    您想在 django 模型的抽象层(通过覆盖模型实例的保存方法)中更上一层楼吗?

    你真的有必要这样做吗?

    抽象是 OOPS 的组成部分之一。因此,在实际需要您超越抽象层之前,为什么要这样做呢? 显然密码可以在 ModelForm 的save() 方法中进行哈希处理。

    另外,如果你在抽象上再上一层, 如果将来发生意外行为怎么办?

    在我看来,为什么不把它留在 ModelForm 中呢?当我们开始使用 django 时,我们从抽象的最高层开始(我们只是调用方法,通常不知道我们继承的类中发生了什么;这就是 oops 的用途)只有在出现了特定的需求。

    希望这能以某种方式指导您。谢谢。

    【讨论】:

    • 我真的很感谢您的研究和时间来回答这个问题。我之所以将覆盖切换到模型定义,是因为我最终肯定必须覆盖其他一些save() 函数,并且它们可能来自不依赖于任何形式的模型,因此在一个地方完成所有覆盖似乎更有条理,而不是让它们遍布代码,在单独的层和单独的 Django 元素上。您对此有何看法?
    • 显然是的。如果许多模型都需要大量的保存方法,那么只在模型中覆盖保存方法会很整洁。(如果一个人的目标是一个大项目,那么将它全部组织起来应该始终是一个问题)。虽然,我必须补充一点,在 Model 的 Save 方法中你必须更加小心。它直接与数据库通信,一个微小的错误可能会带来很多麻烦。除此之外,我认为应该没有任何问题。毕竟,如果在模型级别提供了“保存”方法,那么我们不应该太犹豫使用它。
    • 同意。我会将您的答案标记为好,在它和这些 cmets 之间,我认为我们已经涵盖了大部分问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多