我想向我的用户公开ORM控件。我并不是说我希望他们在部分代码中添加内容,我的意思是我想让他们实际编写django代码。我只需要允许特定模型,并且只允许获取数据(不添加或更改任何内容)。会有一个控制台,每一行都会被执行(有点像ipython笔记本),返回的数据(如果它是一个QuerySet对象)将显示在某种表格中。
此功能仅供我的超级用户管理员使用,因此不会引起安全问题。什么是最好的方法(如果可能的话)?
更新
也许我应该为这里的预期用法提供一些背景知识。请参阅我已经构建了一个收集和保存统计信息的应用程序。我的用户有很多我为他们构建的过滤器,但是他们不断要求提供越来越多的灵活性,有时他们需要过滤非常具体的东西,这只是一次性的事情,所以我不能继续添加越来越多的东西特征
现在我的超级用户知道一个小蟒蛇,我知道也许我可以给他们一些自己过滤的方法。我们的想法是,他们将能够保存查询并为其命名,然后将这些自定义过滤器添加到主站点上的列表中。
它的工作方式是获取一个包含所有对象的QuerySet对象,他们可以使用预定命令列表进行过滤。运行该命令后,服务器将对其进行评估,查找错误或禁止的代码,然后才会运行它。但我猜我不能在生产服务器中使用eval()
,现在可以吗?那还有其他一些方法吗?
答案 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的建议标记为答案,看看如何真正完整的控制台式控制可能是正确的方向