允许管理员通过视图控制Django ORM

时间:2014-01-06 22:40:32

标签: python django

我想向我的用户公开ORM控件。我并不是说我希望他们在部分代码中添加内容,我的意思是我想让他们实际编写django代码。我只需要允许特定模型,并且只允许获取数据(不添加或更改任何内容)。会有一个控制台,每一行都会被执行(有点像ipython笔记本),返回的数据(如果它是一个QuerySet对象)将显示在某种表格中。

此功能仅供我的超级用户管理员使用,因此不会引起安全问题。什么是最好的方法(如果可能的话)?

更新

也许我应该为这里的预期用法提供一些背景知识。请参阅我已经构建了一个收集和保存统计信息的应用程序。我的用户有很多我为他们构建的过滤器,但是他们不断要求提供越来越多的灵活性,有时他们需要过滤非常具体的东西,这只是一次性的事情,所以我不能继续添加越来越多的东西特征

现在我的超级用户知道一个小蟒蛇,我知道也许我可以给他们一些自己过滤的方法。我们的想法是,他们将能够保存查询并为其命名,然后将这些自定义过滤器添加到主站点上的列表中。

它的工作方式是获取一个包含所有对象的QuerySet对象,他们可以使用预定命令列表进行过滤。运行该命令后,服务器将对其进行评估,查找错误或禁止的代码,然后才会运行它。但我猜我不能在生产服务器中使用eval(),现在可以吗?那还有其他一些方法吗?

4 个答案:

答案 0 :(得分:1)

  

我想让他们真正写下django代码

这意味着允许某些用户访问编写Django,并通过扩展Python编写代码。如果没有让管理员用户终端访问现场机器上的代码,这是不可能的。如果你确实让终端访问了代码,那么成为安全问题,因为简单的语法错误可能会导致整个网站崩溃。

此外,如果您这样做,用户的每次更改都需要重新同步数据库,他们可能会对syncdb甚至South的模型进行更改。无法处理意味着您的数据无法恢复且网站无法正常运行。

重新设计您的应用程序,以便通过更改对象实例而不是目标代码本身来实现灵活性。

答案 1 :(得分:1)

在服务器/usr/local/sbin/djshell上添加文件

#!/bin/sh
cd /path/to/project/
/path/to/python /path/to/project/manage.py shell #or "dbshell" or custom interactive task

使用此shell添加用户

useradd -s /usr/local/sbin/djshell -g www-data [more options] superdjangoadmin

允许通过ssh登录。用户直接连接到django shell,类型from app.models import *,这就是你所需要的。

从这个shell中,用户可以破坏可访问的数据。您必须确保所有数据都是只读的。 也许使用settings.py的副本运行它,其中DATABASES设置为只读用户名。

自定义shell的伪代码

#imports
command = input()#expecting "filter(...).last()" or so
cleanup(command) #remove ";", "eval()", escape parameter values, strip
command = "MyModel.objects." + command
try:
    result = eval(command)
    prettyprint(result)

except Exception as e:
    print get_traceback()        
    print e.message

答案 2 :(得分:0)

如果管理员知道SQL - 给他们phpmyadmin提供只读的privelegies。

答案 3 :(得分:0)

在搞砸了一下之后,我意识到我正在寻找比我想象的更简单的东西。以下是对此外观的快速了解(Item是一个包含两个字段的测试模型,电子邮件和名称):

服务器端:

def qs_eval(request):
    items = Item.objects.all()
    code = ''
    if request.method == 'GET':
        code = request.GET['code']
        cleaned = map(lambda x: x.strip(), code.split(','))
        commands = dict([x.split('=') for x in cleaned if x])
        items = items.filter(**commands)        

    return render_to_response('qs_eval.html', {'items': items, 'code': code})

HTML:

<form>
    <input type='text' name='code' value='{{ code }}' />
    <button cls='btn'>send!</button>
</form>

<table class='table'>
    <thead>
    <tr>
        <th>name</th>
        <th>email</th>
    </tr>
    </thead>

    <tbody>
    {% for i in items %}
        <tr>
            <td>{{ i.name }}</td>
            <td>{{ i.email }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>

显然,这里没有错误处理,我只允许过滤,但很容易将其扩展到其他功能,例如exclude和more,以及pythonically检查任何no-no等代码。

无论如何,这就是我最终做的事情。我仍然会将@ eri的建议标记为答案,看看如何真正完整的控制台式控制可能是正确的方向