如何将 Django 模型设为只读?

Posted

技术标签:

【中文标题】如何将 Django 模型设为只读?【英文标题】:How can I make a Django model read-only? 【发布时间】:2012-08-22 21:56:09 【问题描述】:

是否可以将 Django 模型设为只读?没有创建、更新等。

注意这个问题不同于:

Make a Django model read-only?(这个问题允许创建新记录)

Whole model as read-only(仅涉及 Django 管理界面 - 我希望该模型在整个应用程序中都是只读的)

【问题讨论】:

【参考方案1】:

覆盖模型的保存和删除方法。您打算如何将对象添加到模型中?

def save(self, *args, **kwargs):
     return

def delete(self, *args, **kwargs):
     return

【讨论】:

"您打算如何将对象添加到您的模型中?" -> 可能在纯 sql 中,或者来自另一个 webapp。 好的,那么上面应该可以工作了。如果您愿意,也可以在有人尝试保存/删除模型时引发异常。 FWIW,您还需要定义一个自定义管理器来保护那里的createupdatedelete 方法。 "您打算如何将对象添加到您的模型中?" -> 有时将非托管模型映射到数据库视图非常方便,而不是表。【参考方案2】:

您可以在模型的Meta 中设置managed = False

from django.db import models

class MyReadOnlyModel(models.Model):
    class Meta:
        managed = False

如果False,则不会对该模型执行任何数据库表创建或删除操作。如果模型表示现有表或已通过其他方式创建的数据库视图,这将非常有用。

https://docs.djangoproject.com/en/dev/ref/models/options/#managed

【讨论】:

这仍然允许插入或删除记录,只跳过创建和删除 恕我直言,这是答案的有效部分,因为只读也应该防止数据库迁移。【参考方案3】:

数据库路由器

要采取更多预防措施,您的模型是只读的,您可以使用DATABASE_ROUTERS 设置来禁用每个模型的写入:

# settings.py
DATABASE_ROUTERS = ('dbrouters.MyCustomRouter', )


# dbrouters.py
class MyCustomRouter(object):
    def db_for_write(self, model, **hints):
        if model == MyReadOnlyModel:
            raise Exception("This model is read only. Shame!")
         return None

我认为这是一项保险单,而不是解决问题的主要方法。例如,Mikael 的回答很好,但并未涵盖所有情况,因为一些 Django 操作绕过了 deletesave 方法。

有关使用数据库路由器的更详细说明,请参阅 Juan José Brown 在Django - how to specify a database for a model? 中的回答。

设置数据库用户权限

然而,即使是数据库路由器方法似乎也存在漏洞,即有一些方法可以绕过您的路由器代码从 Django 发送 SQL。要绝对确定将某些内容设为只读,您应该设置数据库用户的权限。 This question 描述了如何设置一个只读的 postgreql 用户,该用户可以是 Django 在settings.DATABASES 中设置的数据库用户。

【讨论】:

以上是关于如何将 Django 模型设为只读?的主要内容,如果未能解决你的问题,请参考以下文章

我可以将一个美味的模型资源字段设为只读吗?

Django admin:将必填字段设为只读

模板中的只读表单,django

依赖于模型的 Django 小部件

Django Admin Cookbook-39如何两次向Django管理员添加模型

只读模型并在django admin中显示为列表?